diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2014-08-07 06:23:41 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-08-07 14:40:08 -0400 |
| commit | 215752fce31c80f3b3a1530bc7cddb3ba6a69b3a (patch) | |
| tree | 70274a8d3ba397085593cf98be126a376f9221bf /kernel | |
| parent | 54a4d58a6459a93fc6ee898354b3d2ffb80dd03a (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.c | 135 |
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 | ||
| 80 | struct bsd_acct_struct { | 81 | struct 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 | ||
| 90 | static DEFINE_SPINLOCK(acct_lock); | 92 | static DEFINE_SPINLOCK(acct_lock); |
| 91 | static 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 | ||
| 136 | static struct bsd_acct_struct *acct_get(struct bsd_acct_struct **p) | 137 | static 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 | |||
| 152 | static 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); |
| 140 | again: | 156 | again: |
| 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 | /** | 283 | void 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 | */ | ||
| 277 | void 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) |
| 282 | restart: | 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 | /** | 296 | void 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 | */ | ||
| 309 | void 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) |
| 314 | restart: | 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 | ||
| 334 | void acct_exit_ns(struct pid_namespace *ns) | 309 | void 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) | |||
| 602 | static void slow_acct_process(struct pid_namespace *ns) | 577 | static 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); |
