X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/5d10e64732b909d9e22bab9557f55a0fd7928d2b..6b8f7051f2b8ef9bd16f7fb52d3226972bd3aa4f:/usr/src/sys/kern/kern_acct.c diff --git a/usr/src/sys/kern/kern_acct.c b/usr/src/sys/kern/kern_acct.c index e932c94114..235c2e0b54 100644 --- a/usr/src/sys/kern/kern_acct.c +++ b/usr/src/sys/kern/kern_acct.c @@ -1,130 +1,198 @@ -/* kern_acct.c 6.6 84/12/12 */ +/*- + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * %sccs.include.proprietary.c% + * + * @(#)kern_acct.c 8.6 (Berkeley) %G% + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#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" +/* + * 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 acctchkfreq = 15; /* frequency (in seconds) to check space */ /* * 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() +struct acct_args { + char *fname; +}; +acct(p, uap, retval) + struct proc *p; + struct acct_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 (suser()) { - if (savacctp) { - acctp = savacctp; - savacctp = NULL; + if (error = suser(p->p_ucred, &p->p_acflag)) + return (error); + if (savacctp) { + acctp = savacctp; + savacctp = NULL; + } + if (uap->fname == NULL) { + if (vp = acctp) { + acctp = NULL; + error = vn_close(vp, FWRITE, p->p_ucred, p); + untimeout(acctwatch, NULL); } - if (uap->fname==NULL) { - if (ip = acctp) { - irele(ip); - acctp = NULL; - } + return (error); + } + 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); + } + oacctp = acctp; + acctp = vp; + if (oacctp) + error = vn_close(oacctp, FWRITE, p->p_ucred, p); + acctwatch(NULL); + return (error); +} + +/* + * Periodically check the file system to see if accounting + * should be turned on or off. Beware the case where the vnode + * has been vgone()'d out from underneath us, e.g. when the file + * system containing the accounting file has been forcibly unmounted. + */ +/* ARGSUSED */ +void +acctwatch(a) + void *a; +{ + struct statfs sb; + + if (savacctp) { + if (savacctp->v_type == VBAD) { + (void) vn_close(savacctp, FWRITE, NOCRED, NULL); + savacctp = NULL; return; } - ndp->ni_nameiop = LOOKUP | FOLLOW; - ndp->ni_segflg = UIO_USERSPACE; - ndp->ni_dirp = uap->fname; - ip = namei(ndp); - if(ip == NULL) + (void)VFS_STATFS(savacctp->v_mount, &sb, (struct proc *)0); + if (sb.f_bavail > acctresume * sb.f_blocks / 100) { + acctp = savacctp; + savacctp = NULL; + log(LOG_NOTICE, "Accounting resumed\n"); + } + } else { + if (acctp == NULL) return; - if((ip->i_mode & IFMT) != IFREG) { - u.u_error = EACCES; - iput(ip); + if (acctp->v_type == VBAD) { + (void) vn_close(acctp, FWRITE, NOCRED, NULL); + acctp = NULL; return; } - if (acctp && (acctp->i_number != ip->i_number || - acctp->i_dev != ip->i_dev)) - irele(acctp); - acctp = ip; - iunlock(ip); + (void)VFS_STATFS(acctp->v_mount, &sb, (struct proc *)0); + if (sb.f_bavail <= acctsuspend * sb.f_blocks / 100) { + savacctp = acctp; + acctp = NULL; + log(LOG_NOTICE, "Accounting suspended\n"); + } } + timeout(acctwatch, NULL, acctchkfreq * hz); } -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. + * This routine calculates an accounting record for a process and, + * if accounting is enabled, writes it to the accounting file. */ -acct() +acct_process(p) + register struct proc *p; { - register int i; - register struct inode *ip; - register struct fs *fs; register struct rusage *ru; - off_t siz; - struct timeval t; + struct vnode *vp; + struct timeval t, ut, st; + int error, i, s; + struct acct acctbuf; register struct acct *ap = &acctbuf; - if (savacctp) { - fs = savacctp->i_fs; - if (freespace(fs, fs->fs_minfree + acctresume) > 0) { - acctp = savacctp; - savacctp = NULL; - printf("Accounting resumed\n"); - } + s = splclock(); + if ((vp = acctp) == NULL) { + splx(s); + return (0); } - if ((ip = acctp) == NULL) - return; - fs = acctp->i_fs; - if (freespace(fs, fs->fs_minfree + acctsuspend) <= 0) { - savacctp = acctp; + if (vp->v_type == VBAD) { + (void) vn_close(vp, FWRITE, NOCRED, NULL); acctp = NULL; - printf("Accounting suspended\n"); - return; + splx(s); + return (0); } - ilock(ip); - for (i = 0; i < sizeof (ap->ac_comm); i++) - ap->ac_comm[i] = u.u_comm[i]; - 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); + bcopy(p->p_comm, ap->ac_comm, sizeof(ap->ac_comm)); + ru = &p->p_stats->p_ru; + calcru(p, &ut, &st, NULL); t = time; - timevalsub(&t, &u.u_start); + 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_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) - 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; - ap->ac_mem >>= CLSIZELOG2; - ap->ac_io = compress(ru->ru_inblock + ru->ru_oublock, 0); - if (u.u_ttyp) - ap->ac_tty = u.u_ttyd; + ap->ac_io = compress(ru->ru_inblock + ru->ru_oublock, (long)0); + if (p->p_flag & P_CONTROLT && p->p_session->s_ttyp) + ap->ac_tty = p->p_session->s_ttyp->t_dev; 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; + VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); + error = 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); + splx(s); + return (error); } /*