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