/* * Close the old accouting file (if currently open) and then replace * it with file (if non-NULL). * * NOTE: acct_globals.lock MUST be held on entry and exit. */ static void acct_file_reopen(struct file *file) { struct file *old_acct = NULL; if (acct_globals.file) { old_acct = acct_globals.file; del_timer(&acct_globals.timer); acct_globals.active = 0; acct_globals.needcheck = 0; acct_globals.file = NULL; } if (file) { acct_globals.file = file; acct_globals.needcheck = 0; acct_globals.active = 1; /* It's been deleted if it was used before so this is safe */ init_timer(&acct_globals.timer); acct_globals.timer.function = acct_timeout; acct_globals.timer.expires = jiffies + ACCT_TIMEOUT*HZ; add_timer(&acct_globals.timer); } if (old_acct) { spin_unlock(&acct_globals.lock); do_acct_process(0, old_acct); filp_close(old_acct, NULL); spin_lock(&acct_globals.lock); } }
/* * Close the old accounting file (if currently open) and then replace * it with file (if non-NULL). * * NOTE: acct_lock MUST be held on entry and exit. */ static void acct_file_reopen(struct bsd_acct_struct *acct, struct file *file, struct pid_namespace *ns) { struct file *old_acct = NULL; struct pid_namespace *old_ns = NULL; if (acct->file) { old_acct = acct->file; old_ns = acct->ns; del_timer(&acct->timer); acct->active = 0; acct->needcheck = 0; acct->file = NULL; acct->ns = NULL; list_del(&acct->list); } if (file) { acct->file = file; acct->ns = ns; acct->needcheck = 0; acct->active = 1; list_add(&acct->list, &acct_list); /* It's been deleted if it was used before so this is safe */ setup_timer(&acct->timer, acct_timeout, (unsigned long)acct); acct->timer.expires = jiffies + ACCT_TIMEOUT*HZ; add_timer(&acct->timer); } if (old_acct) { mnt_unpin(old_acct->f_path.mnt); spin_unlock(&acct_lock); do_acct_process(acct, old_ns, old_acct); filp_close(old_acct, NULL); spin_lock(&acct_lock); } }
/* * Close the old accounting file (if currently open) and then replace * it with file (if non-NULL). * * NOTE: acct_lock MUST be held on entry and exit. */ static void acct_file_reopen(struct bsd_acct_struct *acct, struct file *file, struct pid_namespace *ns) { struct file *old_acct = NULL; struct pid_namespace *old_ns = NULL; if (acct->file) { old_acct = acct->file; old_ns = acct->ns; acct->active = 0; acct->file = NULL; acct->ns = NULL; list_del(&acct->list); } if (file) { acct->file = file; acct->ns = ns; acct->needcheck = jiffies + ACCT_TIMEOUT*HZ; acct->active = 1; list_add(&acct->list, &acct_list); } if (old_acct) { mnt_unpin(old_acct->f_path.mnt); spin_unlock(&acct_lock); do_acct_process(acct, old_ns, old_acct); filp_close(old_acct, NULL); spin_lock(&acct_lock); } }
/* * sys_acct() is the only system call needed to implement process * accounting. It takes the name of the file where accounting records * should be written. If the filename is NULL, accounting will be * shutdown. */ asmlinkage long sys_acct(const char *name) { struct file *file = NULL, *old_acct = NULL; char *tmp; int error; if (!capable(CAP_SYS_PACCT)) return -EPERM; if (name) { tmp = getname(name); error = PTR_ERR(tmp); if (IS_ERR(tmp)) goto out; /* Difference from BSD - they don't do O_APPEND */ file = filp_open(tmp, O_WRONLY|O_APPEND, 0); putname(tmp); if (IS_ERR(file)) { error = PTR_ERR(file); goto out; } error = -EACCES; if (!S_ISREG(file->f_dentry->d_inode->i_mode)) goto out_err; error = -EIO; if (!file->f_op->write) goto out_err; } error = 0; lock_kernel(); if (acct_file) { old_acct = acct_file; del_timer(&acct_timer); acct_active = 0; acct_needcheck = 0; acct_file = NULL; } if (name) { acct_file = file; acct_needcheck = 0; acct_active = 1; /* It's been deleted if it was used before so this is safe */ init_timer(&acct_timer); acct_timer.function = acct_timeout; acct_timer.expires = jiffies + ACCT_TIMEOUT*HZ; add_timer(&acct_timer); } unlock_kernel(); if (old_acct) { do_acct_process(0,old_acct); filp_close(old_acct, NULL); } out: return error; out_err: filp_close(file, NULL); goto out; }
/* * Close the old accounting file (if currently open) and then replace * it with file (if non-NULL). * * NOTE: acct_globals.lock MUST be held on entry and exit. */ static void acct_file_reopen(struct file *file) { struct file *old_acct = NULL; struct pid_namespace *old_ns = NULL; if (acct_globals.file) { old_acct = acct_globals.file; old_ns = acct_globals.ns; del_timer(&acct_globals.timer); acct_globals.active = 0; acct_globals.needcheck = 0; acct_globals.file = NULL; } if (file) { acct_globals.file = file; acct_globals.ns = get_pid_ns(task_active_pid_ns(current)); acct_globals.needcheck = 0; acct_globals.active = 1; /* It's been deleted if it was used before so this is safe */ init_timer(&acct_globals.timer); acct_globals.timer.function = acct_timeout; acct_globals.timer.expires = jiffies + ACCT_TIMEOUT*HZ; add_timer(&acct_globals.timer); } if (old_acct) { mnt_unpin(old_acct->f_path.mnt); spin_unlock(&acct_globals.lock); do_acct_process(old_ns, old_acct); filp_close(old_acct, NULL); put_pid_ns(old_ns); spin_lock(&acct_globals.lock); } }
/* * sys_acct() is the only system call needed to implement process * accounting. It takes the name of the file where accounting records * should be written. If the filename is NULL, accounting will be * shutdown. */ asmlinkage int sys_acct(const char *name) { struct file *file = NULL, *old_acct = NULL; char *tmp; int error = -EPERM; lock_kernel(); if (!capable(CAP_SYS_PACCT)) goto out; if (name) { tmp = getname(name); error = PTR_ERR(tmp); if (IS_ERR(tmp)) goto out; /* Difference from BSD - they don't do O_APPEND */ file = filp_open(tmp, O_WRONLY|O_APPEND, 0); putname(tmp); if (IS_ERR(file)) { error = PTR_ERR(file); goto out; } error = -EACCES; if (!S_ISREG(file->f_dentry->d_inode->i_mode)) goto out_err; error = -EIO; if (!file->f_op->write) goto out_err; } error = 0; if (acct_file) { old_acct = acct_file; del_timer(&acct_timer); acct_active = 0; acct_needcheck = 0; acct_file = NULL; } if (name) { acct_file = file; acct_needcheck = 0; acct_active = 1; acct_timer.expires = jiffies + ACCT_TIMEOUT*HZ; add_timer(&acct_timer); } if (old_acct) { do_acct_process(0,old_acct); fput(old_acct); } out: unlock_kernel(); return error; out_err: fput(file); goto out; }
static void acct_pin_kill(struct fs_pin *pin) { struct bsd_acct_struct *acct = to_acct(pin); mutex_lock(&acct->lock); do_acct_process(acct); schedule_work(&acct->work); wait_for_completion(&acct->done); cmpxchg(&acct->ns->bacct, pin, NULL); mutex_unlock(&acct->lock); pin_remove(pin); acct_put(acct); }