move read/writeblkvp from old ufs_io.c to spec_read/write
[unix-history] / usr / src / sys / kern / kern_acct.c
CommitLineData
da7c5cc6 1/*
c4ec2128 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
be555728
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
da7c5cc6 5 *
be555728 6 * @(#)kern_acct.c 7.7 (Berkeley) %G%
da7c5cc6 7 */
06138e31 8
94368568
JB
9#include "param.h"
10#include "systm.h"
556dc220
MK
11#include "time.h"
12#include "proc.h"
94368568 13#include "user.h"
c4ec2128
KM
14#include "vnode.h"
15#include "mount.h"
94368568
JB
16#include "kernel.h"
17#include "acct.h"
18#include "uio.h"
c4ec2128
KM
19#include "syslog.h"
20
21/*
22 * Values associated with enabling and disabling accounting
23 */
24int acctsuspend = 2; /* stop accounting when < 2% free space left */
25int acctresume = 4; /* resume when free space risen to > 4% */
26struct timeval chk = { 15, 0 };/* frequency to check space for accounting */
06138e31
SL
27
28/*
29 * SHOULD REPLACE THIS WITH A DRIVER THAT CAN BE READ TO SIMPLIFY.
30 */
c4ec2128
KM
31struct vnode *acctp;
32struct vnode *savacctp;
06138e31
SL
33
34/*
35 * Perform process accounting functions.
36 */
37sysacct()
38{
c4ec2128 39 register struct vnode *vp;
06138e31
SL
40 register struct a {
41 char *fname;
42 } *uap = (struct a *)u.u_ap;
715baff1 43 register struct nameidata *ndp = &u.u_nd;
c4ec2128
KM
44 extern int acctwatch();
45 struct vnode *oacctp;
06138e31 46
849cbd39
KM
47 if (u.u_error = suser(u.u_cred, &u.u_acflag))
48 return;
49 if (savacctp) {
50 acctp = savacctp;
51 savacctp = NULL;
52 }
53 if (uap->fname==NULL) {
c4ec2128 54 if (vp = acctp) {
849cbd39 55 acctp = NULL;
c4ec2128
KM
56 vrele(vp);
57 untimeout(acctwatch, (caddr_t)&chk);
dbba2129 58 }
849cbd39
KM
59 return;
60 }
61 ndp->ni_nameiop = LOOKUP | FOLLOW;
62 ndp->ni_segflg = UIO_USERSPACE;
63 ndp->ni_dirp = uap->fname;
c4ec2128 64 if (u.u_error = namei(ndp))
849cbd39 65 return;
c4ec2128
KM
66 vp = ndp->ni_vp;
67 if (vp->v_type != VREG) {
849cbd39 68 u.u_error = EACCES;
c4ec2128 69 vrele(vp);
849cbd39
KM
70 return;
71 }
c4ec2128 72 if (vp->v_mount->m_flag & M_RDONLY) {
849cbd39 73 u.u_error = EROFS;
c4ec2128 74 vrele(vp);
849cbd39 75 return;
06138e31 76 }
c4ec2128
KM
77 oacctp = acctp;
78 acctp = vp;
79 if (oacctp)
80 vrele(oacctp);
81 acctwatch(&chk);
06138e31
SL
82}
83
06138e31 84/*
c4ec2128
KM
85 * Periodically check the file system to see if accounting
86 * should be turned on or off.
06138e31 87 */
c4ec2128
KM
88acctwatch(resettime)
89 struct timeval *resettime;
06138e31 90{
c4ec2128 91 struct statfs sb;
06138e31
SL
92
93 if (savacctp) {
c4ec2128
KM
94 (void)VFS_STATFS(savacctp->v_mount, &sb);
95 if (sb.f_bavail > acctresume * sb.f_blocks / 100) {
06138e31
SL
96 acctp = savacctp;
97 savacctp = NULL;
c4ec2128
KM
98 log(LOG_NOTICE, "Accounting resumed\n");
99 return;
06138e31
SL
100 }
101 }
c4ec2128 102 if (acctp == NULL)
06138e31 103 return;
c4ec2128
KM
104 (void)VFS_STATFS(acctp->v_mount, &sb);
105 if (sb.f_bavail <= acctsuspend * sb.f_blocks / 100) {
06138e31
SL
106 savacctp = acctp;
107 acctp = NULL;
c4ec2128 108 log(LOG_NOTICE, "Accounting suspended\n");
06138e31 109 }
c4ec2128
KM
110 timeout(acctwatch, (caddr_t)resettime, hzto(resettime));
111}
112
113/*
114 * On exit, write a record on the accounting file.
115 */
116acct()
117{
118 register struct rusage *ru;
119 struct vnode *vp;
120 struct timeval t;
121 int i;
122 struct acct acctbuf;
123 register struct acct *ap = &acctbuf;
124
125 if ((vp = acctp) == NULL)
126 return;
9fa0dc60 127 bcopy(u.u_comm, ap->ac_comm, sizeof(ap->ac_comm));
032146e9
SL
128 ru = &u.u_ru;
129 ap->ac_utime = compress(ru->ru_utime.tv_sec, ru->ru_utime.tv_usec);
130 ap->ac_stime = compress(ru->ru_stime.tv_sec, ru->ru_stime.tv_usec);
131 t = time;
132 timevalsub(&t, &u.u_start);
133 ap->ac_etime = compress(t.tv_sec, t.tv_usec);
134 ap->ac_btime = u.u_start.tv_sec;
556dc220
MK
135 ap->ac_uid = u.u_procp->p_ruid;
136 ap->ac_gid = u.u_procp->p_rgid;
032146e9
SL
137 t = ru->ru_stime;
138 timevaladd(&t, &ru->ru_utime);
350f5463 139 if (i = t.tv_sec * hz + t.tv_usec / tick)
032146e9
SL
140 ap->ac_mem = (ru->ru_ixrss+ru->ru_idrss+ru->ru_isrss) / i;
141 else
142 ap->ac_mem = 0;
143 ap->ac_mem >>= CLSIZELOG2;
01b0e233 144 ap->ac_io = compress(ru->ru_inblock + ru->ru_oublock, (long)0);
06138e31
SL
145 if (u.u_ttyp)
146 ap->ac_tty = u.u_ttyd;
147 else
148 ap->ac_tty = NODEV;
149 ap->ac_flag = u.u_acflag;
c4ec2128
KM
150 u.u_error = vn_rdwr(UIO_WRITE, vp, (caddr_t)ap, sizeof (acctbuf),
151 (off_t)0, UIO_SYSSPACE, IO_UNIT|IO_APPEND, u.u_cred, (int *)0);
06138e31
SL
152}
153
154/*
155 * Produce a pseudo-floating point representation
156 * with 3 bits base-8 exponent, 13 bits fraction.
157 */
032146e9 158compress(t, ut)
06138e31 159 register long t;
032146e9 160 long ut;
06138e31
SL
161{
162 register exp = 0, round = 0;
163
5d10e647 164 t = t * AHZ; /* compiler will convert only this format to a shift */
032146e9 165 if (ut)
5d10e647 166 t += ut / (1000000 / AHZ);
06138e31
SL
167 while (t >= 8192) {
168 exp++;
169 round = t&04;
170 t >>= 3;
171 }
172 if (round) {
173 t++;
174 if (t >= 8192) {
175 t >>= 3;
176 exp++;
177 }
178 }
179 return ((exp<<13) + t);
180}