xref: /original-bsd/sys/kern/kern_acct.c (revision 87a44d1b)
1 /*
2  * Copyright (c) 1982, 1986 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  *
6  *	@(#)kern_acct.c	7.3 (Berkeley) 10/18/88
7  */
8 
9 #include "param.h"
10 #include "systm.h"
11 #include "dir.h"
12 #include "user.h"
13 #include "inode.h"
14 #include "fs.h"
15 #include "kernel.h"
16 #include "acct.h"
17 #include "uio.h"
18 
19 /*
20  * SHOULD REPLACE THIS WITH A DRIVER THAT CAN BE READ TO SIMPLIFY.
21  */
22 struct	inode *acctp;
23 struct	inode *savacctp;
24 
25 /*
26  * Perform process accounting functions.
27  */
28 sysacct()
29 {
30 	register struct inode *ip;
31 	register struct a {
32 		char	*fname;
33 	} *uap = (struct a *)u.u_ap;
34 	register struct nameidata *ndp = &u.u_nd;
35 
36 	if (suser()) {
37 		if (savacctp) {
38 			acctp = savacctp;
39 			savacctp = NULL;
40 		}
41 		if (uap->fname==NULL) {
42 			if (ip = acctp) {
43 				acctp = NULL;
44 				irele(ip);
45 			}
46 			return;
47 		}
48 		ndp->ni_nameiop = LOOKUP | FOLLOW;
49 		ndp->ni_segflg = UIO_USERSPACE;
50 		ndp->ni_dirp = uap->fname;
51 		ip = namei(ndp);
52 		if (ip == NULL)
53 			return;
54 		if ((ip->i_mode&IFMT) != IFREG) {
55 			u.u_error = EACCES;
56 			iput(ip);
57 			return;
58 		}
59 		if (ip->i_fs->fs_ronly) {
60 			u.u_error = EROFS;
61 			iput(ip);
62 			return;
63 		}
64 		if (acctp && (acctp->i_number != ip->i_number ||
65 		    acctp->i_dev != ip->i_dev))
66 			irele(acctp);
67 		acctp = ip;
68 		iunlock(ip);
69 	}
70 }
71 
72 int	acctsuspend = 2;	/* stop accounting when < 2% free space left */
73 int	acctresume = 4;		/* resume when free space risen to > 4% */
74 
75 struct	acct acctbuf;
76 /*
77  * On exit, write a record on the accounting file.
78  */
79 acct()
80 {
81 	register int i;
82 	register struct inode *ip;
83 	register struct fs *fs;
84 	register struct rusage *ru;
85 	off_t siz;
86 	struct timeval t;
87 	register struct acct *ap = &acctbuf;
88 
89 	if (savacctp) {
90 		fs = savacctp->i_fs;
91 		if (freespace(fs, fs->fs_minfree + acctresume) > 0) {
92 			acctp = savacctp;
93 			savacctp = NULL;
94 			printf("Accounting resumed\n");
95 		}
96 	}
97 	if ((ip = acctp) == NULL)
98 		return;
99 	fs = acctp->i_fs;
100 	if (freespace(fs, fs->fs_minfree + acctsuspend) <= 0) {
101 		savacctp = acctp;
102 		acctp = NULL;
103 		printf("Accounting suspended\n");
104 		return;
105 	}
106 	ilock(ip);
107 	bcopy(u.u_comm, ap->ac_comm, sizeof(ap->ac_comm));
108 	ru = &u.u_ru;
109 	ap->ac_utime = compress(ru->ru_utime.tv_sec, ru->ru_utime.tv_usec);
110 	ap->ac_stime = compress(ru->ru_stime.tv_sec, ru->ru_stime.tv_usec);
111 	t = time;
112 	timevalsub(&t, &u.u_start);
113 	ap->ac_etime = compress(t.tv_sec, t.tv_usec);
114 	ap->ac_btime = u.u_start.tv_sec;
115 	ap->ac_uid = u.u_ruid;
116 	ap->ac_gid = u.u_rgid;
117 	t = ru->ru_stime;
118 	timevaladd(&t, &ru->ru_utime);
119 	if (i = t.tv_sec * hz + t.tv_usec / tick)
120 		ap->ac_mem = (ru->ru_ixrss+ru->ru_idrss+ru->ru_isrss) / i;
121 	else
122 		ap->ac_mem = 0;
123 	ap->ac_mem >>= CLSIZELOG2;
124 	ap->ac_io = compress(ru->ru_inblock + ru->ru_oublock, (long)0);
125 	if (u.u_ttyp)
126 		ap->ac_tty = u.u_ttyd;
127 	else
128 		ap->ac_tty = NODEV;
129 	ap->ac_flag = u.u_acflag;
130 	siz = ip->i_size;
131 	u.u_error = 0;				/* XXX */
132 	u.u_error =
133 	    rdwri(UIO_WRITE, ip, (caddr_t)ap, sizeof (acctbuf), siz,
134 		1, (int *)0);
135 	if (u.u_error)
136 		itrunc(ip, (u_long)siz);
137 	iunlock(ip);
138 }
139 
140 /*
141  * Produce a pseudo-floating point representation
142  * with 3 bits base-8 exponent, 13 bits fraction.
143  */
144 compress(t, ut)
145 	register long t;
146 	long ut;
147 {
148 	register exp = 0, round = 0;
149 
150 	t = t * AHZ;  /* compiler will convert only this format to a shift */
151 	if (ut)
152 		t += ut / (1000000 / AHZ);
153 	while (t >= 8192) {
154 		exp++;
155 		round = t&04;
156 		t >>= 3;
157 	}
158 	if (round) {
159 		t++;
160 		if (t >= 8192) {
161 			t >>= 3;
162 			exp++;
163 		}
164 	}
165 	return ((exp<<13) + t);
166 }
167