forked from Minki/linux
bsdacct: switch from global bsd_acct_struct instance to per-pidns one
Allocate the structure on the first call to sys_acct(). After this each namespace, that ordered the accounting, will live with this structure till its own death. Two notes - routines, that close the accounting on fs umount time use the init_pid_ns's acct by now; - accounting routine accounts to dying task's namespace (also by now). Signed-off-by: Pavel Emelyanov <xemul@openvz.org> Cc: Balbir Singh <balbir@in.ibm.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
6248b1b342
commit
0b6b030fc3
@ -120,17 +120,20 @@ struct acct_v3
|
|||||||
struct vfsmount;
|
struct vfsmount;
|
||||||
struct super_block;
|
struct super_block;
|
||||||
struct pacct_struct;
|
struct pacct_struct;
|
||||||
|
struct pid_namespace;
|
||||||
extern void acct_auto_close_mnt(struct vfsmount *m);
|
extern void acct_auto_close_mnt(struct vfsmount *m);
|
||||||
extern void acct_auto_close(struct super_block *sb);
|
extern void acct_auto_close(struct super_block *sb);
|
||||||
extern void acct_init_pacct(struct pacct_struct *pacct);
|
extern void acct_init_pacct(struct pacct_struct *pacct);
|
||||||
extern void acct_collect(long exitcode, int group_dead);
|
extern void acct_collect(long exitcode, int group_dead);
|
||||||
extern void acct_process(void);
|
extern void acct_process(void);
|
||||||
|
extern void acct_exit_ns(struct pid_namespace *);
|
||||||
#else
|
#else
|
||||||
#define acct_auto_close_mnt(x) do { } while (0)
|
#define acct_auto_close_mnt(x) do { } while (0)
|
||||||
#define acct_auto_close(x) do { } while (0)
|
#define acct_auto_close(x) do { } while (0)
|
||||||
#define acct_init_pacct(x) do { } while (0)
|
#define acct_init_pacct(x) do { } while (0)
|
||||||
#define acct_collect(x,y) do { } while (0)
|
#define acct_collect(x,y) do { } while (0)
|
||||||
#define acct_process() do { } while (0)
|
#define acct_process() do { } while (0)
|
||||||
|
#define acct_exit_ns(ns) do { } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -93,8 +93,6 @@ struct bsd_acct_struct {
|
|||||||
|
|
||||||
static DEFINE_SPINLOCK(acct_lock);
|
static DEFINE_SPINLOCK(acct_lock);
|
||||||
|
|
||||||
static struct bsd_acct_struct acct_globals __cacheline_aligned;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called whenever the timer says to check the free space.
|
* Called whenever the timer says to check the free space.
|
||||||
*/
|
*/
|
||||||
@ -176,7 +174,8 @@ out:
|
|||||||
*
|
*
|
||||||
* NOTE: acct_lock MUST be held on entry and exit.
|
* NOTE: acct_lock MUST be held on entry and exit.
|
||||||
*/
|
*/
|
||||||
static void acct_file_reopen(struct bsd_acct_struct *acct, struct file *file)
|
static void acct_file_reopen(struct bsd_acct_struct *acct, struct file *file,
|
||||||
|
struct pid_namespace *ns)
|
||||||
{
|
{
|
||||||
struct file *old_acct = NULL;
|
struct file *old_acct = NULL;
|
||||||
struct pid_namespace *old_ns = NULL;
|
struct pid_namespace *old_ns = NULL;
|
||||||
@ -188,10 +187,11 @@ static void acct_file_reopen(struct bsd_acct_struct *acct, struct file *file)
|
|||||||
acct->active = 0;
|
acct->active = 0;
|
||||||
acct->needcheck = 0;
|
acct->needcheck = 0;
|
||||||
acct->file = NULL;
|
acct->file = NULL;
|
||||||
|
acct->ns = NULL;
|
||||||
}
|
}
|
||||||
if (file) {
|
if (file) {
|
||||||
acct->file = file;
|
acct->file = file;
|
||||||
acct->ns = get_pid_ns(task_active_pid_ns(current));
|
acct->ns = ns;
|
||||||
acct->needcheck = 0;
|
acct->needcheck = 0;
|
||||||
acct->active = 1;
|
acct->active = 1;
|
||||||
/* It's been deleted if it was used before so this is safe */
|
/* It's been deleted if it was used before so this is safe */
|
||||||
@ -204,7 +204,6 @@ static void acct_file_reopen(struct bsd_acct_struct *acct, struct file *file)
|
|||||||
spin_unlock(&acct_lock);
|
spin_unlock(&acct_lock);
|
||||||
do_acct_process(acct, old_ns, old_acct);
|
do_acct_process(acct, old_ns, old_acct);
|
||||||
filp_close(old_acct, NULL);
|
filp_close(old_acct, NULL);
|
||||||
put_pid_ns(old_ns);
|
|
||||||
spin_lock(&acct_lock);
|
spin_lock(&acct_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,6 +212,8 @@ static int acct_on(char *name)
|
|||||||
{
|
{
|
||||||
struct file *file;
|
struct file *file;
|
||||||
int error;
|
int error;
|
||||||
|
struct pid_namespace *ns;
|
||||||
|
struct bsd_acct_struct *acct = NULL;
|
||||||
|
|
||||||
/* Difference from BSD - they don't do O_APPEND */
|
/* Difference from BSD - they don't do O_APPEND */
|
||||||
file = filp_open(name, O_WRONLY|O_APPEND|O_LARGEFILE, 0);
|
file = filp_open(name, O_WRONLY|O_APPEND|O_LARGEFILE, 0);
|
||||||
@ -229,18 +230,34 @@ static int acct_on(char *name)
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ns = task_active_pid_ns(current);
|
||||||
|
if (ns->bacct == NULL) {
|
||||||
|
acct = kzalloc(sizeof(struct bsd_acct_struct), GFP_KERNEL);
|
||||||
|
if (acct == NULL) {
|
||||||
|
filp_close(file, NULL);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
error = security_acct(file);
|
error = security_acct(file);
|
||||||
if (error) {
|
if (error) {
|
||||||
|
kfree(acct);
|
||||||
filp_close(file, NULL);
|
filp_close(file, NULL);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock(&acct_lock);
|
spin_lock(&acct_lock);
|
||||||
|
if (ns->bacct == NULL) {
|
||||||
|
ns->bacct = acct;
|
||||||
|
acct = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
mnt_pin(file->f_path.mnt);
|
mnt_pin(file->f_path.mnt);
|
||||||
acct_file_reopen(&acct_globals, file);
|
acct_file_reopen(ns->bacct, file, ns);
|
||||||
spin_unlock(&acct_lock);
|
spin_unlock(&acct_lock);
|
||||||
|
|
||||||
mntput(file->f_path.mnt); /* it's pinned, now give up active reference */
|
mntput(file->f_path.mnt); /* it's pinned, now give up active reference */
|
||||||
|
kfree(acct);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -270,10 +287,16 @@ asmlinkage long sys_acct(const char __user *name)
|
|||||||
error = acct_on(tmp);
|
error = acct_on(tmp);
|
||||||
putname(tmp);
|
putname(tmp);
|
||||||
} else {
|
} else {
|
||||||
|
struct bsd_acct_struct *acct;
|
||||||
|
|
||||||
|
acct = task_active_pid_ns(current)->bacct;
|
||||||
|
if (acct == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
error = security_acct(NULL);
|
error = security_acct(NULL);
|
||||||
if (!error) {
|
if (!error) {
|
||||||
spin_lock(&acct_lock);
|
spin_lock(&acct_lock);
|
||||||
acct_file_reopen(&acct_globals, NULL);
|
acct_file_reopen(acct, NULL, NULL);
|
||||||
spin_unlock(&acct_lock);
|
spin_unlock(&acct_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -289,9 +312,15 @@ asmlinkage long sys_acct(const char __user *name)
|
|||||||
*/
|
*/
|
||||||
void acct_auto_close_mnt(struct vfsmount *m)
|
void acct_auto_close_mnt(struct vfsmount *m)
|
||||||
{
|
{
|
||||||
|
struct bsd_acct_struct *acct;
|
||||||
|
|
||||||
|
acct = init_pid_ns.bacct;
|
||||||
|
if (acct == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
spin_lock(&acct_lock);
|
spin_lock(&acct_lock);
|
||||||
if (acct_globals.file && acct_globals.file->f_path.mnt == m)
|
if (acct->file && acct->file->f_path.mnt == m)
|
||||||
acct_file_reopen(&acct_globals, NULL);
|
acct_file_reopen(acct, NULL, NULL);
|
||||||
spin_unlock(&acct_lock);
|
spin_unlock(&acct_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,10 +333,29 @@ void acct_auto_close_mnt(struct vfsmount *m)
|
|||||||
*/
|
*/
|
||||||
void acct_auto_close(struct super_block *sb)
|
void acct_auto_close(struct super_block *sb)
|
||||||
{
|
{
|
||||||
|
struct bsd_acct_struct *acct;
|
||||||
|
|
||||||
|
acct = init_pid_ns.bacct;
|
||||||
|
if (acct == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
spin_lock(&acct_lock);
|
spin_lock(&acct_lock);
|
||||||
if (acct_globals.file &&
|
if (acct->file && acct->file->f_path.mnt->mnt_sb == sb)
|
||||||
acct_globals.file->f_path.mnt->mnt_sb == sb) {
|
acct_file_reopen(acct, NULL, NULL);
|
||||||
acct_file_reopen(&acct_globals, NULL);
|
spin_unlock(&acct_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void acct_exit_ns(struct pid_namespace *ns)
|
||||||
|
{
|
||||||
|
struct bsd_acct_struct *acct;
|
||||||
|
|
||||||
|
spin_lock(&acct_lock);
|
||||||
|
acct = ns->bacct;
|
||||||
|
if (acct != NULL) {
|
||||||
|
if (acct->file != NULL)
|
||||||
|
acct_file_reopen(acct, NULL, NULL);
|
||||||
|
|
||||||
|
kfree(acct);
|
||||||
}
|
}
|
||||||
spin_unlock(&acct_lock);
|
spin_unlock(&acct_lock);
|
||||||
}
|
}
|
||||||
@ -587,25 +635,25 @@ void acct_collect(long exitcode, int group_dead)
|
|||||||
void acct_process(void)
|
void acct_process(void)
|
||||||
{
|
{
|
||||||
struct file *file = NULL;
|
struct file *file = NULL;
|
||||||
struct pid_namespace *ns;
|
struct pid_namespace *ns = task_active_pid_ns(current);
|
||||||
|
struct bsd_acct_struct *acct;
|
||||||
|
|
||||||
|
acct = ns->bacct;
|
||||||
/*
|
/*
|
||||||
* accelerate the common fastpath:
|
* accelerate the common fastpath:
|
||||||
*/
|
*/
|
||||||
if (!acct_globals.file)
|
if (!acct || !acct->file)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
spin_lock(&acct_lock);
|
spin_lock(&acct_lock);
|
||||||
file = acct_globals.file;
|
file = acct->file;
|
||||||
if (unlikely(!file)) {
|
if (unlikely(!file)) {
|
||||||
spin_unlock(&acct_lock);
|
spin_unlock(&acct_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
get_file(file);
|
get_file(file);
|
||||||
ns = get_pid_ns(acct_globals.ns);
|
|
||||||
spin_unlock(&acct_lock);
|
spin_unlock(&acct_lock);
|
||||||
|
|
||||||
do_acct_process(&acct_globals, ns, file);
|
do_acct_process(acct, ns, file);
|
||||||
fput(file);
|
fput(file);
|
||||||
put_pid_ns(ns);
|
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <linux/pid_namespace.h>
|
#include <linux/pid_namespace.h>
|
||||||
#include <linux/syscalls.h>
|
#include <linux/syscalls.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
|
#include <linux/acct.h>
|
||||||
|
|
||||||
#define BITS_PER_PAGE (PAGE_SIZE*8)
|
#define BITS_PER_PAGE (PAGE_SIZE*8)
|
||||||
|
|
||||||
@ -181,6 +182,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)
|
|||||||
|
|
||||||
/* Child reaper for the pid namespace is going away */
|
/* Child reaper for the pid namespace is going away */
|
||||||
pid_ns->child_reaper = NULL;
|
pid_ns->child_reaper = NULL;
|
||||||
|
acct_exit_ns(pid_ns);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user