new naming convention
[unix-history] / usr / src / sys / kern / kern_acct.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 *
17 * @(#)kern_acct.c 7.5 (Berkeley) %G%
18 */
19
20#include "param.h"
21#include "systm.h"
22#include "user.h"
23#include "vnode.h"
24#include "mount.h"
25#include "kernel.h"
26#include "acct.h"
27#include "uio.h"
28#include "syslog.h"
29
30/*
31 * Values associated with enabling and disabling accounting
32 */
33int acctsuspend = 2; /* stop accounting when < 2% free space left */
34int acctresume = 4; /* resume when free space risen to > 4% */
35struct timeval chk = { 15, 0 };/* frequency to check space for accounting */
36
37/*
38 * SHOULD REPLACE THIS WITH A DRIVER THAT CAN BE READ TO SIMPLIFY.
39 */
40struct vnode *acctp;
41struct vnode *savacctp;
42
43/*
44 * Perform process accounting functions.
45 */
46sysacct()
47{
48 register struct vnode *vp;
49 register struct a {
50 char *fname;
51 } *uap = (struct a *)u.u_ap;
52 register struct nameidata *ndp = &u.u_nd;
53 extern int acctwatch();
54 struct vnode *oacctp;
55
56 if (u.u_error = suser(u.u_cred, &u.u_acflag))
57 return;
58 if (savacctp) {
59 acctp = savacctp;
60 savacctp = NULL;
61 }
62 if (uap->fname==NULL) {
63 if (vp = acctp) {
64 acctp = NULL;
65 vrele(vp);
66 untimeout(acctwatch, (caddr_t)&chk);
67 }
68 return;
69 }
70 ndp->ni_nameiop = LOOKUP | FOLLOW;
71 ndp->ni_segflg = UIO_USERSPACE;
72 ndp->ni_dirp = uap->fname;
73 if (u.u_error = namei(ndp))
74 return;
75 vp = ndp->ni_vp;
76 if (vp->v_type != VREG) {
77 u.u_error = EACCES;
78 vrele(vp);
79 return;
80 }
81 if (vp->v_mount->m_flag & M_RDONLY) {
82 u.u_error = EROFS;
83 vrele(vp);
84 return;
85 }
86 oacctp = acctp;
87 acctp = vp;
88 if (oacctp)
89 vrele(oacctp);
90 acctwatch(&chk);
91}
92
93/*
94 * Periodically check the file system to see if accounting
95 * should be turned on or off.
96 */
97acctwatch(resettime)
98 struct timeval *resettime;
99{
100 struct statfs sb;
101
102 if (savacctp) {
103 (void)VFS_STATFS(savacctp->v_mount, &sb);
104 if (sb.f_bavail > acctresume * sb.f_blocks / 100) {
105 acctp = savacctp;
106 savacctp = NULL;
107 log(LOG_NOTICE, "Accounting resumed\n");
108 return;
109 }
110 }
111 if (acctp == NULL)
112 return;
113 (void)VFS_STATFS(acctp->v_mount, &sb);
114 if (sb.f_bavail <= acctsuspend * sb.f_blocks / 100) {
115 savacctp = acctp;
116 acctp = NULL;
117 log(LOG_NOTICE, "Accounting suspended\n");
118 }
119 timeout(acctwatch, (caddr_t)resettime, hzto(resettime));
120}
121
122/*
123 * On exit, write a record on the accounting file.
124 */
125acct()
126{
127 register struct rusage *ru;
128 struct vnode *vp;
129 struct timeval t;
130 int i;
131 struct acct acctbuf;
132 register struct acct *ap = &acctbuf;
133
134 if ((vp = acctp) == NULL)
135 return;
136 bcopy(u.u_comm, ap->ac_comm, sizeof(ap->ac_comm));
137 ru = &u.u_ru;
138 ap->ac_utime = compress(ru->ru_utime.tv_sec, ru->ru_utime.tv_usec);
139 ap->ac_stime = compress(ru->ru_stime.tv_sec, ru->ru_stime.tv_usec);
140 t = time;
141 timevalsub(&t, &u.u_start);
142 ap->ac_etime = compress(t.tv_sec, t.tv_usec);
143 ap->ac_btime = u.u_start.tv_sec;
144 ap->ac_uid = u.u_ruid;
145 ap->ac_gid = u.u_rgid;
146 t = ru->ru_stime;
147 timevaladd(&t, &ru->ru_utime);
148 if (i = t.tv_sec * hz + t.tv_usec / tick)
149 ap->ac_mem = (ru->ru_ixrss+ru->ru_idrss+ru->ru_isrss) / i;
150 else
151 ap->ac_mem = 0;
152 ap->ac_mem >>= CLSIZELOG2;
153 ap->ac_io = compress(ru->ru_inblock + ru->ru_oublock, (long)0);
154 if (u.u_ttyp)
155 ap->ac_tty = u.u_ttyd;
156 else
157 ap->ac_tty = NODEV;
158 ap->ac_flag = u.u_acflag;
159 u.u_error = vn_rdwr(UIO_WRITE, vp, (caddr_t)ap, sizeof (acctbuf),
160 (off_t)0, UIO_SYSSPACE, IO_UNIT|IO_APPEND, u.u_cred, (int *)0);
161}
162
163/*
164 * Produce a pseudo-floating point representation
165 * with 3 bits base-8 exponent, 13 bits fraction.
166 */
167compress(t, ut)
168 register long t;
169 long ut;
170{
171 register exp = 0, round = 0;
172
173 t = t * AHZ; /* compiler will convert only this format to a shift */
174 if (ut)
175 t += ut / (1000000 / AHZ);
176 while (t >= 8192) {
177 exp++;
178 round = t&04;
179 t >>= 3;
180 }
181 if (round) {
182 t++;
183 if (t >= 8192) {
184 t >>= 3;
185 exp++;
186 }
187 }
188 return ((exp<<13) + t);
189}