new naming convention
[unix-history] / usr / src / sys / kern / kern_acct.c
CommitLineData
da7c5cc6 1/*
c4ec2128
KM
2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3 * All rights reserved.
da7c5cc6 4 *
c4ec2128
KM
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%
da7c5cc6 18 */
06138e31 19
94368568
JB
20#include "param.h"
21#include "systm.h"
94368568 22#include "user.h"
c4ec2128
KM
23#include "vnode.h"
24#include "mount.h"
94368568
JB
25#include "kernel.h"
26#include "acct.h"
27#include "uio.h"
c4ec2128
KM
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 */
06138e31
SL
36
37/*
38 * SHOULD REPLACE THIS WITH A DRIVER THAT CAN BE READ TO SIMPLIFY.
39 */
c4ec2128
KM
40struct vnode *acctp;
41struct vnode *savacctp;
06138e31
SL
42
43/*
44 * Perform process accounting functions.
45 */
46sysacct()
47{
c4ec2128 48 register struct vnode *vp;
06138e31
SL
49 register struct a {
50 char *fname;
51 } *uap = (struct a *)u.u_ap;
715baff1 52 register struct nameidata *ndp = &u.u_nd;
c4ec2128
KM
53 extern int acctwatch();
54 struct vnode *oacctp;
06138e31 55
849cbd39
KM
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) {
c4ec2128 63 if (vp = acctp) {
849cbd39 64 acctp = NULL;
c4ec2128
KM
65 vrele(vp);
66 untimeout(acctwatch, (caddr_t)&chk);
dbba2129 67 }
849cbd39
KM
68 return;
69 }
70 ndp->ni_nameiop = LOOKUP | FOLLOW;
71 ndp->ni_segflg = UIO_USERSPACE;
72 ndp->ni_dirp = uap->fname;
c4ec2128 73 if (u.u_error = namei(ndp))
849cbd39 74 return;
c4ec2128
KM
75 vp = ndp->ni_vp;
76 if (vp->v_type != VREG) {
849cbd39 77 u.u_error = EACCES;
c4ec2128 78 vrele(vp);
849cbd39
KM
79 return;
80 }
c4ec2128 81 if (vp->v_mount->m_flag & M_RDONLY) {
849cbd39 82 u.u_error = EROFS;
c4ec2128 83 vrele(vp);
849cbd39 84 return;
06138e31 85 }
c4ec2128
KM
86 oacctp = acctp;
87 acctp = vp;
88 if (oacctp)
89 vrele(oacctp);
90 acctwatch(&chk);
06138e31
SL
91}
92
06138e31 93/*
c4ec2128
KM
94 * Periodically check the file system to see if accounting
95 * should be turned on or off.
06138e31 96 */
c4ec2128
KM
97acctwatch(resettime)
98 struct timeval *resettime;
06138e31 99{
c4ec2128 100 struct statfs sb;
06138e31
SL
101
102 if (savacctp) {
c4ec2128
KM
103 (void)VFS_STATFS(savacctp->v_mount, &sb);
104 if (sb.f_bavail > acctresume * sb.f_blocks / 100) {
06138e31
SL
105 acctp = savacctp;
106 savacctp = NULL;
c4ec2128
KM
107 log(LOG_NOTICE, "Accounting resumed\n");
108 return;
06138e31
SL
109 }
110 }
c4ec2128 111 if (acctp == NULL)
06138e31 112 return;
c4ec2128
KM
113 (void)VFS_STATFS(acctp->v_mount, &sb);
114 if (sb.f_bavail <= acctsuspend * sb.f_blocks / 100) {
06138e31
SL
115 savacctp = acctp;
116 acctp = NULL;
c4ec2128 117 log(LOG_NOTICE, "Accounting suspended\n");
06138e31 118 }
c4ec2128
KM
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;
9fa0dc60 136 bcopy(u.u_comm, ap->ac_comm, sizeof(ap->ac_comm));
032146e9
SL
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;
06138e31
SL
144 ap->ac_uid = u.u_ruid;
145 ap->ac_gid = u.u_rgid;
032146e9
SL
146 t = ru->ru_stime;
147 timevaladd(&t, &ru->ru_utime);
350f5463 148 if (i = t.tv_sec * hz + t.tv_usec / tick)
032146e9
SL
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;
01b0e233 153 ap->ac_io = compress(ru->ru_inblock + ru->ru_oublock, (long)0);
06138e31
SL
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;
c4ec2128
KM
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);
06138e31
SL
161}
162
163/*
164 * Produce a pseudo-floating point representation
165 * with 3 bits base-8 exponent, 13 bits fraction.
166 */
032146e9 167compress(t, ut)
06138e31 168 register long t;
032146e9 169 long ut;
06138e31
SL
170{
171 register exp = 0, round = 0;
172
5d10e647 173 t = t * AHZ; /* compiler will convert only this format to a shift */
032146e9 174 if (ut)
5d10e647 175 t += ut / (1000000 / AHZ);
06138e31
SL
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}