|
@@ -54,6 +54,7 @@
|
|
#include <linux/jiffies.h>
|
|
#include <linux/jiffies.h>
|
|
#include <linux/times.h>
|
|
#include <linux/times.h>
|
|
#include <linux/syscalls.h>
|
|
#include <linux/syscalls.h>
|
|
|
|
+#include <linux/mount.h>
|
|
#include <asm/uaccess.h>
|
|
#include <asm/uaccess.h>
|
|
#include <asm/div64.h>
|
|
#include <asm/div64.h>
|
|
#include <linux/blkdev.h> /* sector_div */
|
|
#include <linux/blkdev.h> /* sector_div */
|
|
@@ -192,6 +193,7 @@ static void acct_file_reopen(struct file *file)
|
|
add_timer(&acct_globals.timer);
|
|
add_timer(&acct_globals.timer);
|
|
}
|
|
}
|
|
if (old_acct) {
|
|
if (old_acct) {
|
|
|
|
+ mnt_unpin(old_acct->f_vfsmnt);
|
|
spin_unlock(&acct_globals.lock);
|
|
spin_unlock(&acct_globals.lock);
|
|
do_acct_process(0, old_acct);
|
|
do_acct_process(0, old_acct);
|
|
filp_close(old_acct, NULL);
|
|
filp_close(old_acct, NULL);
|
|
@@ -199,6 +201,42 @@ static void acct_file_reopen(struct file *file)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int acct_on(char *name)
|
|
|
|
+{
|
|
|
|
+ struct file *file;
|
|
|
|
+ int error;
|
|
|
|
+
|
|
|
|
+ /* Difference from BSD - they don't do O_APPEND */
|
|
|
|
+ file = filp_open(name, O_WRONLY|O_APPEND|O_LARGEFILE, 0);
|
|
|
|
+ if (IS_ERR(file))
|
|
|
|
+ return PTR_ERR(file);
|
|
|
|
+
|
|
|
|
+ if (!S_ISREG(file->f_dentry->d_inode->i_mode)) {
|
|
|
|
+ filp_close(file, NULL);
|
|
|
|
+ return -EACCES;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!file->f_op->write) {
|
|
|
|
+ filp_close(file, NULL);
|
|
|
|
+ return -EIO;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ error = security_acct(file);
|
|
|
|
+ if (error) {
|
|
|
|
+ filp_close(file, NULL);
|
|
|
|
+ return error;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ spin_lock(&acct_globals.lock);
|
|
|
|
+ mnt_pin(file->f_vfsmnt);
|
|
|
|
+ acct_file_reopen(file);
|
|
|
|
+ spin_unlock(&acct_globals.lock);
|
|
|
|
+
|
|
|
|
+ mntput(file->f_vfsmnt); /* it's pinned, now give up active reference */
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* sys_acct - enable/disable process accounting
|
|
* sys_acct - enable/disable process accounting
|
|
* @name: file name for accounting records or NULL to shutdown accounting
|
|
* @name: file name for accounting records or NULL to shutdown accounting
|
|
@@ -212,47 +250,41 @@ static void acct_file_reopen(struct file *file)
|
|
*/
|
|
*/
|
|
asmlinkage long sys_acct(const char __user *name)
|
|
asmlinkage long sys_acct(const char __user *name)
|
|
{
|
|
{
|
|
- struct file *file = NULL;
|
|
|
|
- char *tmp;
|
|
|
|
int error;
|
|
int error;
|
|
|
|
|
|
if (!capable(CAP_SYS_PACCT))
|
|
if (!capable(CAP_SYS_PACCT))
|
|
return -EPERM;
|
|
return -EPERM;
|
|
|
|
|
|
if (name) {
|
|
if (name) {
|
|
- tmp = getname(name);
|
|
|
|
- if (IS_ERR(tmp)) {
|
|
|
|
|
|
+ char *tmp = getname(name);
|
|
|
|
+ if (IS_ERR(tmp))
|
|
return (PTR_ERR(tmp));
|
|
return (PTR_ERR(tmp));
|
|
- }
|
|
|
|
- /* Difference from BSD - they don't do O_APPEND */
|
|
|
|
- file = filp_open(tmp, O_WRONLY|O_APPEND|O_LARGEFILE, 0);
|
|
|
|
|
|
+ error = acct_on(tmp);
|
|
putname(tmp);
|
|
putname(tmp);
|
|
- if (IS_ERR(file)) {
|
|
|
|
- return (PTR_ERR(file));
|
|
|
|
- }
|
|
|
|
- if (!S_ISREG(file->f_dentry->d_inode->i_mode)) {
|
|
|
|
- filp_close(file, NULL);
|
|
|
|
- return (-EACCES);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (!file->f_op->write) {
|
|
|
|
- filp_close(file, NULL);
|
|
|
|
- return (-EIO);
|
|
|
|
|
|
+ } else {
|
|
|
|
+ error = security_acct(NULL);
|
|
|
|
+ if (!error) {
|
|
|
|
+ spin_lock(&acct_globals.lock);
|
|
|
|
+ acct_file_reopen(NULL);
|
|
|
|
+ spin_unlock(&acct_globals.lock);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ return error;
|
|
|
|
+}
|
|
|
|
|
|
- error = security_acct(file);
|
|
|
|
- if (error) {
|
|
|
|
- if (file)
|
|
|
|
- filp_close(file, NULL);
|
|
|
|
- return error;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
|
|
+/**
|
|
|
|
+ * acct_auto_close - turn off a filesystem's accounting if it is on
|
|
|
|
+ * @m: vfsmount being shut down
|
|
|
|
+ *
|
|
|
|
+ * If the accounting is turned on for a file in the subtree pointed to
|
|
|
|
+ * to by m, turn accounting off. Done when m is about to die.
|
|
|
|
+ */
|
|
|
|
+void acct_auto_close_mnt(struct vfsmount *m)
|
|
|
|
+{
|
|
spin_lock(&acct_globals.lock);
|
|
spin_lock(&acct_globals.lock);
|
|
- acct_file_reopen(file);
|
|
|
|
|
|
+ if (acct_globals.file && acct_globals.file->f_vfsmnt == m)
|
|
|
|
+ acct_file_reopen(NULL);
|
|
spin_unlock(&acct_globals.lock);
|
|
spin_unlock(&acct_globals.lock);
|
|
-
|
|
|
|
- return (0);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -266,8 +298,8 @@ void acct_auto_close(struct super_block *sb)
|
|
{
|
|
{
|
|
spin_lock(&acct_globals.lock);
|
|
spin_lock(&acct_globals.lock);
|
|
if (acct_globals.file &&
|
|
if (acct_globals.file &&
|
|
- acct_globals.file->f_dentry->d_inode->i_sb == sb) {
|
|
|
|
- acct_file_reopen((struct file *)NULL);
|
|
|
|
|
|
+ acct_globals.file->f_vfsmnt->mnt_sb == sb) {
|
|
|
|
+ acct_file_reopen(NULL);
|
|
}
|
|
}
|
|
spin_unlock(&acct_globals.lock);
|
|
spin_unlock(&acct_globals.lock);
|
|
}
|
|
}
|