Commit | Line | Data |
---|---|---|
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 | * |
46e4c6f8 | 6 | * @(#)kern_acct.c 7.14 (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" | |
8c7d0e2a KM |
13 | #include "ioctl.h" |
14 | #include "termios.h" | |
15 | #include "tty.h" | |
d9c2f47f | 16 | #include "user.h" |
c4ec2128 KM |
17 | #include "vnode.h" |
18 | #include "mount.h" | |
94368568 | 19 | #include "kernel.h" |
46e4c6f8 | 20 | #include "file.h" |
94368568 JB |
21 | #include "acct.h" |
22 | #include "uio.h" | |
c4ec2128 KM |
23 | #include "syslog.h" |
24 | ||
25 | /* | |
26 | * Values associated with enabling and disabling accounting | |
27 | */ | |
28 | int acctsuspend = 2; /* stop accounting when < 2% free space left */ | |
29 | int acctresume = 4; /* resume when free space risen to > 4% */ | |
30 | struct timeval chk = { 15, 0 };/* frequency to check space for accounting */ | |
06138e31 SL |
31 | |
32 | /* | |
33 | * SHOULD REPLACE THIS WITH A DRIVER THAT CAN BE READ TO SIMPLIFY. | |
34 | */ | |
c4ec2128 KM |
35 | struct vnode *acctp; |
36 | struct vnode *savacctp; | |
06138e31 SL |
37 | |
38 | /* | |
39 | * Perform process accounting functions. | |
40 | */ | |
8c7d0e2a KM |
41 | /* ARGSUSED */ |
42 | sysacct(p, uap, retval) | |
43 | struct proc *p; | |
44 | struct args { | |
45 | char *fname; | |
46 | } *uap; | |
47 | int *retval; | |
06138e31 | 48 | { |
c4ec2128 | 49 | register struct vnode *vp; |
715baff1 | 50 | register struct nameidata *ndp = &u.u_nd; |
c4ec2128 KM |
51 | extern int acctwatch(); |
52 | struct vnode *oacctp; | |
8c7d0e2a | 53 | int error; |
06138e31 | 54 | |
8c7d0e2a | 55 | if (error = suser(u.u_cred, &u.u_acflag)) |
d9c2f47f | 56 | return (error); |
849cbd39 KM |
57 | if (savacctp) { |
58 | acctp = savacctp; | |
59 | savacctp = NULL; | |
60 | } | |
46e4c6f8 | 61 | if (uap->fname == NULL) { |
c4ec2128 | 62 | if (vp = acctp) { |
849cbd39 | 63 | acctp = NULL; |
c4ec2128 KM |
64 | vrele(vp); |
65 | untimeout(acctwatch, (caddr_t)&chk); | |
dbba2129 | 66 | } |
d9c2f47f | 67 | return (0); |
849cbd39 | 68 | } |
849cbd39 KM |
69 | ndp->ni_segflg = UIO_USERSPACE; |
70 | ndp->ni_dirp = uap->fname; | |
46e4c6f8 | 71 | if (error = vn_open(ndp, FWRITE, 0644)) |
d9c2f47f | 72 | return (error); |
c4ec2128 KM |
73 | vp = ndp->ni_vp; |
74 | if (vp->v_type != VREG) { | |
c4ec2128 | 75 | vrele(vp); |
d9c2f47f | 76 | return (EACCES); |
849cbd39 | 77 | } |
c4ec2128 KM |
78 | oacctp = acctp; |
79 | acctp = vp; | |
80 | if (oacctp) | |
81 | vrele(oacctp); | |
82 | acctwatch(&chk); | |
d9c2f47f | 83 | return (0); |
06138e31 SL |
84 | } |
85 | ||
06138e31 | 86 | /* |
c4ec2128 KM |
87 | * Periodically check the file system to see if accounting |
88 | * should be turned on or off. | |
06138e31 | 89 | */ |
c4ec2128 KM |
90 | acctwatch(resettime) |
91 | struct timeval *resettime; | |
06138e31 | 92 | { |
c4ec2128 | 93 | struct statfs sb; |
06138e31 SL |
94 | |
95 | if (savacctp) { | |
c4ec2128 KM |
96 | (void)VFS_STATFS(savacctp->v_mount, &sb); |
97 | if (sb.f_bavail > acctresume * sb.f_blocks / 100) { | |
06138e31 SL |
98 | acctp = savacctp; |
99 | savacctp = NULL; | |
c4ec2128 KM |
100 | log(LOG_NOTICE, "Accounting resumed\n"); |
101 | return; | |
06138e31 SL |
102 | } |
103 | } | |
c4ec2128 | 104 | if (acctp == NULL) |
06138e31 | 105 | return; |
c4ec2128 KM |
106 | (void)VFS_STATFS(acctp->v_mount, &sb); |
107 | if (sb.f_bavail <= acctsuspend * sb.f_blocks / 100) { | |
06138e31 SL |
108 | savacctp = acctp; |
109 | acctp = NULL; | |
c4ec2128 | 110 | log(LOG_NOTICE, "Accounting suspended\n"); |
06138e31 | 111 | } |
c4ec2128 KM |
112 | timeout(acctwatch, (caddr_t)resettime, hzto(resettime)); |
113 | } | |
114 | ||
115 | /* | |
116 | * On exit, write a record on the accounting file. | |
117 | */ | |
8c7d0e2a KM |
118 | acct(p) |
119 | register struct proc *p; | |
c4ec2128 KM |
120 | { |
121 | register struct rusage *ru; | |
122 | struct vnode *vp; | |
1cab08e7 MT |
123 | struct timeval t, ut, st; |
124 | int i, s; | |
c4ec2128 KM |
125 | struct acct acctbuf; |
126 | register struct acct *ap = &acctbuf; | |
127 | ||
128 | if ((vp = acctp) == NULL) | |
8c7d0e2a | 129 | return (0); |
1cab08e7 | 130 | bcopy(p->p_comm, ap->ac_comm, sizeof(ap->ac_comm)); |
032146e9 | 131 | ru = &u.u_ru; |
1cab08e7 MT |
132 | s = splclock(); |
133 | ut = p->p_utime; | |
134 | st = p->p_stime; | |
032146e9 | 135 | t = time; |
1cab08e7 MT |
136 | splx(s); |
137 | ap->ac_utime = compress(ut.tv_sec, ut.tv_usec); | |
138 | ap->ac_stime = compress(st.tv_sec, st.tv_usec); | |
032146e9 SL |
139 | timevalsub(&t, &u.u_start); |
140 | ap->ac_etime = compress(t.tv_sec, t.tv_usec); | |
141 | ap->ac_btime = u.u_start.tv_sec; | |
8c7d0e2a KM |
142 | ap->ac_uid = p->p_ruid; |
143 | ap->ac_gid = p->p_rgid; | |
1cab08e7 MT |
144 | t = st; |
145 | timevaladd(&t, &ut); | |
350f5463 | 146 | if (i = t.tv_sec * hz + t.tv_usec / tick) |
032146e9 SL |
147 | ap->ac_mem = (ru->ru_ixrss+ru->ru_idrss+ru->ru_isrss) / i; |
148 | else | |
149 | ap->ac_mem = 0; | |
01b0e233 | 150 | ap->ac_io = compress(ru->ru_inblock + ru->ru_oublock, (long)0); |
42ee521d | 151 | if (p->p_flag&SCTTY && p->p_session->s_ttyp) |
1cab08e7 | 152 | ap->ac_tty = p->p_session->s_ttyp->t_dev; |
06138e31 SL |
153 | else |
154 | ap->ac_tty = NODEV; | |
155 | ap->ac_flag = u.u_acflag; | |
8c7d0e2a KM |
156 | return (vn_rdwr(UIO_WRITE, vp, (caddr_t)ap, sizeof (acctbuf), |
157 | (off_t)0, UIO_SYSSPACE, IO_UNIT|IO_APPEND, u.u_cred, (int *)0)); | |
06138e31 SL |
158 | } |
159 | ||
160 | /* | |
161 | * Produce a pseudo-floating point representation | |
162 | * with 3 bits base-8 exponent, 13 bits fraction. | |
163 | */ | |
032146e9 | 164 | compress(t, ut) |
06138e31 | 165 | register long t; |
032146e9 | 166 | long ut; |
06138e31 SL |
167 | { |
168 | register exp = 0, round = 0; | |
169 | ||
5d10e647 | 170 | t = t * AHZ; /* compiler will convert only this format to a shift */ |
032146e9 | 171 | if (ut) |
5d10e647 | 172 | t += ut / (1000000 / AHZ); |
06138e31 SL |
173 | while (t >= 8192) { |
174 | exp++; | |
175 | round = t&04; | |
176 | t >>= 3; | |
177 | } | |
178 | if (round) { | |
179 | t++; | |
180 | if (t >= 8192) { | |
181 | t >>= 3; | |
182 | exp++; | |
183 | } | |
184 | } | |
185 | return ((exp<<13) + t); | |
186 | } |