xref: /csrg-svn/sys/kern/kern_acct.c (revision 16695)
1*16695Smckusick /*	kern_acct.c	6.2	84/07/08	*/
212788Ssam 
312788Ssam #include "../h/param.h"
412788Ssam #include "../h/systm.h"
512788Ssam #include "../h/dir.h"
612788Ssam #include "../h/user.h"
712788Ssam #include "../h/inode.h"
812788Ssam #include "../h/fs.h"
912788Ssam #include "../h/kernel.h"
1012788Ssam #include "../h/acct.h"
1112788Ssam #include "../h/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;
28*16695Smckusick 	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 		}
42*16695Smckusick 		ndp->ni_nameiop = LOOKUP | FOLLOW;
43*16695Smckusick 		ndp->ni_segflg = UIO_USERSPACE;
44*16695Smckusick 		ndp->ni_dirp = uap->fname;
45*16695Smckusick 		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;
7312788Ssam 	off_t siz;
7412788Ssam 	register struct acct *ap = &acctbuf;
7512788Ssam 
7612788Ssam 	if (savacctp) {
7712788Ssam 		fs = savacctp->i_fs;
7812788Ssam 		if (freespace(fs, fs->fs_minfree + acctresume) > 0) {
7912788Ssam 			acctp = savacctp;
8012788Ssam 			savacctp = NULL;
8112788Ssam 			printf("Accounting resumed\n");
8212788Ssam 		}
8312788Ssam 	}
8412788Ssam 	if ((ip = acctp) == NULL)
8512788Ssam 		return;
8612788Ssam 	fs = acctp->i_fs;
8712788Ssam 	if (freespace(fs, fs->fs_minfree + acctsuspend) <= 0) {
8812788Ssam 		savacctp = acctp;
8912788Ssam 		acctp = NULL;
9012788Ssam 		printf("Accounting suspended\n");
9112788Ssam 		return;
9212788Ssam 	}
9312788Ssam 	ilock(ip);
9412788Ssam 	for (i = 0; i < sizeof (ap->ac_comm); i++)
9512788Ssam 		ap->ac_comm[i] = u.u_comm[i];
9612788Ssam 	ap->ac_utime = compress((long)u.u_ru.ru_utime.tv_sec);
9712788Ssam 	ap->ac_stime = compress((long)u.u_ru.ru_stime.tv_sec);
9812788Ssam 	ap->ac_etime = compress((long)time.tv_sec - u.u_start);
9912788Ssam 	ap->ac_btime = u.u_start;
10012788Ssam 	ap->ac_uid = u.u_ruid;
10112788Ssam 	ap->ac_gid = u.u_rgid;
10212788Ssam 	ap->ac_mem = 0;
10312788Ssam 	if (i = u.u_ru.ru_utime.tv_sec + u.u_ru.ru_stime.tv_sec)
10412788Ssam 		ap->ac_mem =
10512788Ssam 		    (u.u_ru.ru_ixrss + u.u_ru.ru_idrss + u.u_ru.ru_isrss) / i;
10612788Ssam 	ap->ac_io = compress((long)(u.u_ru.ru_inblock + u.u_ru.ru_oublock));
10712788Ssam 	if (u.u_ttyp)
10812788Ssam 		ap->ac_tty = u.u_ttyd;
10912788Ssam 	else
11012788Ssam 		ap->ac_tty = NODEV;
11112788Ssam 	ap->ac_flag = u.u_acflag;
11212788Ssam 	siz = ip->i_size;
11312788Ssam 	u.u_error = 0;				/* XXX */
11412788Ssam 	u.u_error =
11512788Ssam 	    rdwri(UIO_WRITE, ip, (caddr_t)ap, sizeof (acctbuf), siz,
11612788Ssam 		1, (int *)0);
11712788Ssam 	if (u.u_error)
11812788Ssam 		itrunc(ip, (u_long)siz);
11912788Ssam 	iunlock(ip);
12012788Ssam }
12112788Ssam 
12212788Ssam /*
12312788Ssam  * Produce a pseudo-floating point representation
12412788Ssam  * with 3 bits base-8 exponent, 13 bits fraction.
12512788Ssam  */
12612788Ssam compress(t)
12712788Ssam 	register long t;
12812788Ssam {
12912788Ssam 	register exp = 0, round = 0;
13012788Ssam 
13112788Ssam 	while (t >= 8192) {
13212788Ssam 		exp++;
13312788Ssam 		round = t&04;
13412788Ssam 		t >>= 3;
13512788Ssam 	}
13612788Ssam 	if (round) {
13712788Ssam 		t++;
13812788Ssam 		if (t >= 8192) {
13912788Ssam 			t >>= 3;
14012788Ssam 			exp++;
14112788Ssam 		}
14212788Ssam 	}
14312788Ssam 	return ((exp<<13) + t);
14412788Ssam }
145