date and time created 88/12/14 15:30:11 by sklower
[unix-history] / usr / src / sys / kern / kern_acct.c
CommitLineData
da7c5cc6 1/*
0880b18e 2 * Copyright (c) 1982, 1986 Regents of the University of California.
da7c5cc6
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
9fa0dc60 6 * @(#)kern_acct.c 7.3 (Berkeley) %G%
da7c5cc6 7 */
06138e31 8
94368568
JB
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"
06138e31
SL
18
19/*
20 * SHOULD REPLACE THIS WITH A DRIVER THAT CAN BE READ TO SIMPLIFY.
21 */
22struct inode *acctp;
23struct inode *savacctp;
24
25/*
26 * Perform process accounting functions.
27 */
28sysacct()
29{
30 register struct inode *ip;
31 register struct a {
32 char *fname;
33 } *uap = (struct a *)u.u_ap;
715baff1 34 register struct nameidata *ndp = &u.u_nd;
06138e31
SL
35
36 if (suser()) {
37 if (savacctp) {
38 acctp = savacctp;
39 savacctp = NULL;
40 }
41 if (uap->fname==NULL) {
42 if (ip = acctp) {
06138e31 43 acctp = NULL;
705b524a 44 irele(ip);
06138e31
SL
45 }
46 return;
47 }
715baff1
KM
48 ndp->ni_nameiop = LOOKUP | FOLLOW;
49 ndp->ni_segflg = UIO_USERSPACE;
50 ndp->ni_dirp = uap->fname;
51 ip = namei(ndp);
01b0e233 52 if (ip == NULL)
06138e31 53 return;
01b0e233 54 if ((ip->i_mode&IFMT) != IFREG) {
06138e31
SL
55 u.u_error = EACCES;
56 iput(ip);
57 return;
58 }
dbba2129
KM
59 if (ip->i_fs->fs_ronly) {
60 u.u_error = EROFS;
61 iput(ip);
62 return;
63 }
06138e31
SL
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
72int acctsuspend = 2; /* stop accounting when < 2% free space left */
73int acctresume = 4; /* resume when free space risen to > 4% */
74
75struct acct acctbuf;
76/*
77 * On exit, write a record on the accounting file.
78 */
79acct()
80{
81 register int i;
82 register struct inode *ip;
83 register struct fs *fs;
032146e9 84 register struct rusage *ru;
06138e31 85 off_t siz;
032146e9 86 struct timeval t;
06138e31
SL
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);
9fa0dc60 107 bcopy(u.u_comm, ap->ac_comm, sizeof(ap->ac_comm));
032146e9
SL
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;
06138e31
SL
115 ap->ac_uid = u.u_ruid;
116 ap->ac_gid = u.u_rgid;
032146e9
SL
117 t = ru->ru_stime;
118 timevaladd(&t, &ru->ru_utime);
350f5463 119 if (i = t.tv_sec * hz + t.tv_usec / tick)
032146e9
SL
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;
01b0e233 124 ap->ac_io = compress(ru->ru_inblock + ru->ru_oublock, (long)0);
06138e31
SL
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 */
032146e9 144compress(t, ut)
06138e31 145 register long t;
032146e9 146 long ut;
06138e31
SL
147{
148 register exp = 0, round = 0;
149
5d10e647 150 t = t * AHZ; /* compiler will convert only this format to a shift */
032146e9 151 if (ut)
5d10e647 152 t += ut / (1000000 / AHZ);
06138e31
SL
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}