xref: /csrg-svn/sys/kern/kern_acct.c (revision 17088)
1*17088Sbloom /*	kern_acct.c	6.5	84/08/29	*/
212788Ssam 
3*17088Sbloom #include "param.h"
4*17088Sbloom #include "systm.h"
5*17088Sbloom #include "dir.h"
6*17088Sbloom #include "user.h"
7*17088Sbloom #include "inode.h"
8*17088Sbloom #include "fs.h"
9*17088Sbloom #include "kernel.h"
10*17088Sbloom #include "acct.h"
11*17088Sbloom #include "uio.h"
1212788Ssam 
1312788Ssam /*
1412788Ssam  * SHOULD REPLACE THIS WITH A DRIVER THAT CAN BE READ TO SIMPLIFY.
1512788Ssam  */
1612788Ssam struct	inode *acctp;
1712788Ssam struct	inode *savacctp;
1812788Ssam 
1912788Ssam /*
2012788Ssam  * Perform process accounting functions.
2112788Ssam  */
2212788Ssam sysacct()
2312788Ssam {
2412788Ssam 	register struct inode *ip;
2512788Ssam 	register struct a {
2612788Ssam 		char	*fname;
2712788Ssam 	} *uap = (struct a *)u.u_ap;
2816695Smckusick 	register struct nameidata *ndp = &u.u_nd;
2912788Ssam 
3012788Ssam 	if (suser()) {
3112788Ssam 		if (savacctp) {
3212788Ssam 			acctp = savacctp;
3312788Ssam 			savacctp = NULL;
3412788Ssam 		}
3512788Ssam 		if (uap->fname==NULL) {
3612788Ssam 			if (ip = acctp) {
3712788Ssam 				irele(ip);
3812788Ssam 				acctp = NULL;
3912788Ssam 			}
4012788Ssam 			return;
4112788Ssam 		}
4216695Smckusick 		ndp->ni_nameiop = LOOKUP | FOLLOW;
4316695Smckusick 		ndp->ni_segflg = UIO_USERSPACE;
4416695Smckusick 		ndp->ni_dirp = uap->fname;
4516695Smckusick 		ip = namei(ndp);
4612788Ssam 		if(ip == NULL)
4712788Ssam 			return;
4812788Ssam 		if((ip->i_mode & IFMT) != IFREG) {
4912788Ssam 			u.u_error = EACCES;
5012788Ssam 			iput(ip);
5112788Ssam 			return;
5212788Ssam 		}
5312788Ssam 		if (acctp && (acctp->i_number != ip->i_number ||
5412788Ssam 		    acctp->i_dev != ip->i_dev))
5512788Ssam 			irele(acctp);
5612788Ssam 		acctp = ip;
5712788Ssam 		iunlock(ip);
5812788Ssam 	}
5912788Ssam }
6012788Ssam 
6112788Ssam int	acctsuspend = 2;	/* stop accounting when < 2% free space left */
6212788Ssam int	acctresume = 4;		/* resume when free space risen to > 4% */
6312788Ssam 
6412788Ssam struct	acct acctbuf;
6512788Ssam /*
6612788Ssam  * On exit, write a record on the accounting file.
6712788Ssam  */
6812788Ssam acct()
6912788Ssam {
7012788Ssam 	register int i;
7112788Ssam 	register struct inode *ip;
7212788Ssam 	register struct fs *fs;
7316715Ssam 	register struct rusage *ru;
7412788Ssam 	off_t siz;
7516715Ssam 	struct timeval t;
7612788Ssam 	register struct acct *ap = &acctbuf;
7712788Ssam 
7812788Ssam 	if (savacctp) {
7912788Ssam 		fs = savacctp->i_fs;
8012788Ssam 		if (freespace(fs, fs->fs_minfree + acctresume) > 0) {
8112788Ssam 			acctp = savacctp;
8212788Ssam 			savacctp = NULL;
8312788Ssam 			printf("Accounting resumed\n");
8412788Ssam 		}
8512788Ssam 	}
8612788Ssam 	if ((ip = acctp) == NULL)
8712788Ssam 		return;
8812788Ssam 	fs = acctp->i_fs;
8912788Ssam 	if (freespace(fs, fs->fs_minfree + acctsuspend) <= 0) {
9012788Ssam 		savacctp = acctp;
9112788Ssam 		acctp = NULL;
9212788Ssam 		printf("Accounting suspended\n");
9312788Ssam 		return;
9412788Ssam 	}
9512788Ssam 	ilock(ip);
9612788Ssam 	for (i = 0; i < sizeof (ap->ac_comm); i++)
9712788Ssam 		ap->ac_comm[i] = u.u_comm[i];
9816715Ssam 	ru = &u.u_ru;
9916715Ssam 	ap->ac_utime = compress(ru->ru_utime.tv_sec, ru->ru_utime.tv_usec);
10016715Ssam 	ap->ac_stime = compress(ru->ru_stime.tv_sec, ru->ru_stime.tv_usec);
10116715Ssam 	t = time;
10216715Ssam 	timevalsub(&t, &u.u_start);
10316715Ssam 	ap->ac_etime = compress(t.tv_sec, t.tv_usec);
10416715Ssam 	ap->ac_btime = u.u_start.tv_sec;
10512788Ssam 	ap->ac_uid = u.u_ruid;
10612788Ssam 	ap->ac_gid = u.u_rgid;
10716715Ssam 	t = ru->ru_stime;
10816715Ssam 	timevaladd(&t, &ru->ru_utime);
10916719Skarels 	if (i = t.tv_sec * hz + t.tv_usec / tick)
11016715Ssam 		ap->ac_mem = (ru->ru_ixrss+ru->ru_idrss+ru->ru_isrss) / i;
11116715Ssam 	else
11216715Ssam 		ap->ac_mem = 0;
11316715Ssam 	ap->ac_mem >>= CLSIZELOG2;
11416715Ssam 	ap->ac_io = compress(ru->ru_inblock + ru->ru_oublock, 0);
11512788Ssam 	if (u.u_ttyp)
11612788Ssam 		ap->ac_tty = u.u_ttyd;
11712788Ssam 	else
11812788Ssam 		ap->ac_tty = NODEV;
11912788Ssam 	ap->ac_flag = u.u_acflag;
12012788Ssam 	siz = ip->i_size;
12112788Ssam 	u.u_error = 0;				/* XXX */
12212788Ssam 	u.u_error =
12312788Ssam 	    rdwri(UIO_WRITE, ip, (caddr_t)ap, sizeof (acctbuf), siz,
12412788Ssam 		1, (int *)0);
12512788Ssam 	if (u.u_error)
12612788Ssam 		itrunc(ip, (u_long)siz);
12712788Ssam 	iunlock(ip);
12812788Ssam }
12912788Ssam 
13012788Ssam /*
13112788Ssam  * Produce a pseudo-floating point representation
13212788Ssam  * with 3 bits base-8 exponent, 13 bits fraction.
13312788Ssam  */
13416715Ssam compress(t, ut)
13512788Ssam 	register long t;
13616715Ssam 	long ut;
13712788Ssam {
13812788Ssam 	register exp = 0, round = 0;
13912788Ssam 
14016715Ssam 	t <<= 6;
14116715Ssam 	if (ut)
14216715Ssam 		t += ut / (1000000 / (1<<6));
14312788Ssam 	while (t >= 8192) {
14412788Ssam 		exp++;
14512788Ssam 		round = t&04;
14612788Ssam 		t >>= 3;
14712788Ssam 	}
14812788Ssam 	if (round) {
14912788Ssam 		t++;
15012788Ssam 		if (t >= 8192) {
15112788Ssam 			t >>= 3;
15212788Ssam 			exp++;
15312788Ssam 		}
15412788Ssam 	}
15512788Ssam 	return ((exp<<13) + t);
15612788Ssam }
157