write accounting records with rdwri()
[unix-history] / usr / src / sys / kern / kern_resource.c
/* kern_resource.c 4.11 82/08/22 */
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/acct.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/inode.h"
#include "../h/proc.h"
#include "../h/seg.h"
#include "../h/fs.h"
#include "../h/uio.h"
struct inode *acctp;
struct inode *savacctp;
long acctlow = 2; /* stop accounting when < 2% data space left */
long accthigh = 4; /* resume when space risen to > 4% */
/*
* Perform process accounting functions.
*/
sysacct()
{
register struct inode *ip;
register struct a {
char *fname;
} *uap;
uap = (struct a *)u.u_ap;
if (suser()) {
if (savacctp) {
acctp = savacctp;
savacctp = NULL;
}
if (uap->fname==NULL) {
if (ip = acctp) {
irele(ip);
acctp = NULL;
}
return;
}
ip = namei(uchar, 0, 1);
if(ip == NULL)
return;
if((ip->i_mode & IFMT) != IFREG) {
u.u_error = EACCES;
iput(ip);
return;
}
if (acctp && (acctp->i_number != ip->i_number ||
acctp->i_dev != ip->i_dev))
irele(acctp);
acctp = ip;
iunlock(ip);
}
}
struct acct acctbuf;
/*
* On exit, write a record on the accounting file.
*/
acct()
{
register i;
register struct inode *ip;
off_t siz;
register struct acct *ap = &acctbuf;
if (savacctp && savacctp->i_fs->fs_cstotal.cs_nbfree >
accthigh * savacctp->i_fs->fs_dsize / 100) {
acctp = savacctp;
savacctp = NULL;
printf("Accounting resumed\n");
}
if ((ip=acctp)==NULL)
return;
if (acctp->i_fs->fs_cstotal.cs_nbfree <
acctlow * acctp->i_fs->fs_dsize / 100) {
savacctp = acctp;
acctp = NULL;
printf("Accounting suspended\n");
return;
}
ilock(ip);
for (i=0; i<sizeof(ap->ac_comm); i++)
ap->ac_comm[i] = u.u_comm[i];
ap->ac_utime = compress((long)u.u_vm.vm_utime);
ap->ac_stime = compress((long)u.u_vm.vm_stime);
ap->ac_etime = compress((long)(time - u.u_start));
ap->ac_btime = u.u_start;
ap->ac_uid = u.u_ruid;
ap->ac_gid = u.u_rgid;
ap->ac_mem = 0;
if (i = u.u_vm.vm_utime + u.u_vm.vm_stime)
ap->ac_mem = (u.u_vm.vm_ixrss + u.u_vm.vm_idsrss) / i;
ap->ac_io = compress((long)(u.u_vm.vm_inblk + u.u_vm.vm_oublk));
if (u.u_ttyp)
ap->ac_tty = u.u_ttyd;
else
ap->ac_tty = NODEV;
ap->ac_flag = u.u_acflag;
siz = ip->i_size;
u.u_error =
rdwri(UIO_WRITE, ip, (caddr_t)ap, sizeof (acctbuf), siz,
1, (int *)0);
if (u.u_error)
ip->i_size = siz;
iunlock(ip);
}
/*
* Produce a pseudo-floating point representation
* with 3 bits base-8 exponent, 13 bits fraction.
*/
compress(t)
register long t;
{
register exp = 0, round = 0;
while (t >= 8192) {
exp++;
round = t&04;
t >>= 3;
}
if (round) {
t++;
if (t >= 8192) {
t >>= 3;
exp++;
}
}
return((exp<<13) + t);
}
vtimes()
{
register struct a {
struct vtimes *par_vm;
struct vtimes *ch_vm;
} *uap = (struct a *)u.u_ap;
if (uap->par_vm == 0)
goto onlych;
if (copyout((caddr_t)&u.u_vm, (caddr_t)uap->par_vm,
sizeof(struct vtimes)) < 0)
u.u_error = EFAULT;
onlych:
if (uap->ch_vm == 0)
return;
if (copyout((caddr_t)&u.u_cvm, (caddr_t)uap->ch_vm,
sizeof(struct vtimes)) < 0)
u.u_error = EFAULT;
}
vmsadd(vp, wp)
register struct vtimes *vp, *wp;
{
vp->vm_utime += wp->vm_utime;
vp->vm_stime += wp->vm_stime;
vp->vm_nswap += wp->vm_nswap;
vp->vm_idsrss += wp->vm_idsrss;
vp->vm_ixrss += wp->vm_ixrss;
if (vp->vm_maxrss < wp->vm_maxrss)
vp->vm_maxrss = wp->vm_maxrss;
vp->vm_majflt += wp->vm_majflt;
vp->vm_minflt += wp->vm_minflt;
vp->vm_inblk += wp->vm_inblk;
vp->vm_oublk += wp->vm_oublk;
}