make kernel includes standard
[unix-history] / usr / src / sys / kern / kern_acct.c
index 2994b17..7be6272 100644 (file)
-/*
- * Copyright (c) 1982, 1986 Regents of the University of California.
- * All rights reserved.  The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+/*-
+ * Copyright (c) 1982, 1986, 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.proprietary.c%
  *
  *
- *     @(#)kern_acct.c 7.4 (Berkeley) %G%
+ *     @(#)kern_acct.c 7.26 (Berkeley) %G%
  */
 
  */
 
-#include "param.h"
-#include "systm.h"
-#include "dir.h"
-#include "user.h"
-#include "inode.h"
-#include "fs.h"
-#include "kernel.h"
-#include "acct.h"
-#include "uio.h"
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/namei.h>
+#include <sys/resourcevar.h>
+#include <sys/proc.h>
+#include <sys/ioctl.h>
+#include <sys/termios.h>
+#include <sys/tty.h>
+#include <sys/vnode.h>
+#include <sys/mount.h>
+#include <sys/kernel.h>
+#include <sys/file.h>
+#include <sys/acct.h>
+#include <sys/syslog.h>
+
+/*
+ * Values associated with enabling and disabling accounting
+ */
+int    acctsuspend = 2;        /* stop accounting when < 2% free space left */
+int    acctresume = 4;         /* resume when free space risen to > 4% */
+int    chk = 15;               /* frequency (in seconds) to check space */
 
 /*
  * SHOULD REPLACE THIS WITH A DRIVER THAT CAN BE READ TO SIMPLIFY.
  */
 
 /*
  * SHOULD REPLACE THIS WITH A DRIVER THAT CAN BE READ TO SIMPLIFY.
  */
-struct inode *acctp;
-struct inode *savacctp;
+struct vnode *acctp;
+struct vnode *savacctp;
 
 /*
 
 /*
- * Perform process accounting functions.
+ * Enable or disable process accounting.
+ *
+ * If a non-null filename is given, that file is used to store accounting
+ * records on process exit. If a null filename is given process accounting
+ * is suspended. If accounting is enabled, the system checks the amount
+ * of freespace on the filesystem at timeval intervals. If the amount of
+ * freespace is below acctsuspend percent, accounting is suspended. If
+ * accounting has been suspended, and freespace rises above acctresume,
+ * accounting is resumed.
  */
  */
-sysacct()
+/* ARGSUSED */
+struct sysacct_args {
+       char    *fname;
+};
+sysacct(p, uap, retval)
+       struct proc *p;
+       struct sysacct_args *uap;
+       int *retval;
 {
 {
-       register struct inode *ip;
-       register struct a {
-               char    *fname;
-       } *uap = (struct a *)u.u_ap;
-       register struct nameidata *ndp = &u.u_nd;
+       register struct vnode *vp;
+       extern void acctwatch __P((void *));
+       struct vnode *oacctp;
+       int error;
+       struct nameidata nd;
 
 
-       if (u.u_error = suser(u.u_cred, &u.u_acflag))
-               return;
+       if (error = suser(p->p_ucred, &p->p_acflag))
+               return (error);
        if (savacctp) {
                acctp = savacctp;
                savacctp = NULL;
        }
        if (savacctp) {
                acctp = savacctp;
                savacctp = NULL;
        }
-       if (uap->fname==NULL) {
-               if (ip = acctp) {
+       if (uap->fname == NULL) {
+               if (vp = acctp) {
                        acctp = NULL;
                        acctp = NULL;
-                       irele(ip);
+                       error = vn_close(vp, FWRITE, p->p_ucred, p);
+                       untimeout(acctwatch, NULL);
                }
                }
-               return;
+               return (error);
        }
        }
-       ndp->ni_nameiop = LOOKUP | FOLLOW;
-       ndp->ni_segflg = UIO_USERSPACE;
-       ndp->ni_dirp = uap->fname;
-       ip = namei(ndp);
-       if (ip == NULL)
-               return;
-       if ((ip->i_mode&IFMT) != IFREG) {
-               u.u_error = EACCES;
-               iput(ip);
-               return;
-       }
-       if (ip->i_fs->fs_ronly) {
-               u.u_error = EROFS;
-               iput(ip);
-               return;
+       NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p);
+       if (error = vn_open(&nd, FWRITE, 0644))
+               return (error);
+       vp = nd.ni_vp;
+       VOP_UNLOCK(vp);
+       if (vp->v_type != VREG) {
+               (void) vn_close(vp, FWRITE, p->p_ucred, p);
+               return (EACCES);
        }
        }
-       if (acctp && (acctp->i_number != ip->i_number ||
-           acctp->i_dev != ip->i_dev))
-               irele(acctp);
-       acctp = ip;
-       iunlock(ip);
+       oacctp = acctp;
+       acctp = vp;
+       if (oacctp)
+               error = vn_close(oacctp, FWRITE, p->p_ucred, p);
+       acctwatch(NULL);
+       return (error);
 }
 
 }
 
-int    acctsuspend = 2;        /* stop accounting when < 2% free space left */
-int    acctresume = 4;         /* resume when free space risen to > 4% */
-
-struct acct acctbuf;
 /*
 /*
- * On exit, write a record on the accounting file.
+ * Periodically check the file system to see if accounting
+ * should be turned on or off.
  */
  */
-acct()
+/* ARGSUSED */
+void
+acctwatch(a)
+       void *a;
 {
 {
-       register int i;
-       register struct inode *ip;
-       register struct fs *fs;
-       register struct rusage *ru;
-       off_t siz;
-       struct timeval t;
-       register struct acct *ap = &acctbuf;
+       struct statfs sb;
 
        if (savacctp) {
 
        if (savacctp) {
-               fs = savacctp->i_fs;
-               if (freespace(fs, fs->fs_minfree + acctresume) > 0) {
+               (void)VFS_STATFS(savacctp->v_mount, &sb, (struct proc *)0);
+               if (sb.f_bavail > acctresume * sb.f_blocks / 100) {
                        acctp = savacctp;
                        savacctp = NULL;
                        acctp = savacctp;
                        savacctp = NULL;
-                       printf("Accounting resumed\n");
+                       log(LOG_NOTICE, "Accounting resumed\n");
+                       return;
                }
        }
                }
        }
-       if ((ip = acctp) == NULL)
+       if (acctp == NULL)
                return;
                return;
-       fs = acctp->i_fs;
-       if (freespace(fs, fs->fs_minfree + acctsuspend) <= 0) {
+       (void)VFS_STATFS(acctp->v_mount, &sb, (struct proc *)0);
+       if (sb.f_bavail <= acctsuspend * sb.f_blocks / 100) {
                savacctp = acctp;
                acctp = NULL;
                savacctp = acctp;
                acctp = NULL;
-               printf("Accounting suspended\n");
-               return;
+               log(LOG_NOTICE, "Accounting suspended\n");
        }
        }
-       ilock(ip);
-       bcopy(u.u_comm, ap->ac_comm, sizeof(ap->ac_comm));
-       ru = &u.u_ru;
-       ap->ac_utime = compress(ru->ru_utime.tv_sec, ru->ru_utime.tv_usec);
-       ap->ac_stime = compress(ru->ru_stime.tv_sec, ru->ru_stime.tv_usec);
+       timeout(acctwatch, NULL, chk * hz);
+}
+
+/*
+ * This routine calculates an accounting record for a process and,
+ * if accounting is enabled, writes it to the accounting file.
+ */
+acct(p)
+       register struct proc *p;
+{
+       register struct rusage *ru;
+       struct vnode *vp;
+       struct timeval t, ut, st;
+       int i, s;
+       struct acct acctbuf;
+       register struct acct *ap = &acctbuf;
+
+       if ((vp = acctp) == NULL)
+               return (0);
+       bcopy(p->p_comm, ap->ac_comm, sizeof(ap->ac_comm));
+       ru = &p->p_stats->p_ru;
+       calcru(p, &ut, &st, NULL);
+       s = splclock();
        t = time;
        t = time;
-       timevalsub(&t, &u.u_start);
+       splx(s);
+       ap->ac_utime = compress(ut.tv_sec, ut.tv_usec);
+       ap->ac_stime = compress(st.tv_sec, st.tv_usec);
+       timevalsub(&t, &p->p_stats->p_start);
        ap->ac_etime = compress(t.tv_sec, t.tv_usec);
        ap->ac_etime = compress(t.tv_sec, t.tv_usec);
-       ap->ac_btime = u.u_start.tv_sec;
-       ap->ac_uid = u.u_ruid;
-       ap->ac_gid = u.u_rgid;
-       t = ru->ru_stime;
-       timevaladd(&t, &ru->ru_utime);
+       ap->ac_btime = p->p_stats->p_start.tv_sec;
+       ap->ac_uid = p->p_cred->p_ruid;
+       ap->ac_gid = p->p_cred->p_rgid;
+       t = st;
+       timevaladd(&t, &ut);
        if (i = t.tv_sec * hz + t.tv_usec / tick)
        if (i = t.tv_sec * hz + t.tv_usec / tick)
-               ap->ac_mem = (ru->ru_ixrss+ru->ru_idrss+ru->ru_isrss) / i;
+               ap->ac_mem = (ru->ru_ixrss + ru->ru_idrss + ru->ru_isrss) / i;
        else
                ap->ac_mem = 0;
        else
                ap->ac_mem = 0;
-       ap->ac_mem >>= CLSIZELOG2;
        ap->ac_io = compress(ru->ru_inblock + ru->ru_oublock, (long)0);
        ap->ac_io = compress(ru->ru_inblock + ru->ru_oublock, (long)0);
-       if (u.u_ttyp)
-               ap->ac_tty = u.u_ttyd;
+       if (p->p_flag&SCTTY && p->p_session->s_ttyp)
+               ap->ac_tty = p->p_session->s_ttyp->t_dev;
        else
                ap->ac_tty = NODEV;
        else
                ap->ac_tty = NODEV;
-       ap->ac_flag = u.u_acflag;
-       siz = ip->i_size;
-       u.u_error = 0;                          /* XXX */
-       u.u_error =
-           rdwri(UIO_WRITE, ip, (caddr_t)ap, sizeof (acctbuf), siz,
-               1, (int *)0);
-       if (u.u_error)
-               itrunc(ip, (u_long)siz);
-       iunlock(ip);
+       ap->ac_flag = p->p_acflag;
+       return (vn_rdwr(UIO_WRITE, vp, (caddr_t)ap, sizeof (acctbuf), (off_t)0,
+               UIO_SYSSPACE, IO_UNIT|IO_APPEND, p->p_ucred, (int *)0,
+               (struct proc *)0));
 }
 
 /*
 }
 
 /*