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