Deleted Added
full compact
kern_acct.c (167389) kern_acct.c (169857)
1/*-
2 * Copyright (c) 1982, 1986, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * Copyright (c) 2005 Robert N. M. Watson
6 * All rights reserved.
7 *
8 * All or some portions of this file are derived from material licensed

--- 54 unchanged lines hidden (view full) ---

63 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
64 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65 * SUCH DAMAGE.
66 *
67 * @(#)kern_acct.c 8.1 (Berkeley) 6/14/93
68 */
69
70#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1982, 1986, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * Copyright (c) 2005 Robert N. M. Watson
6 * All rights reserved.
7 *
8 * All or some portions of this file are derived from material licensed

--- 54 unchanged lines hidden (view full) ---

63 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
64 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65 * SUCH DAMAGE.
66 *
67 * @(#)kern_acct.c 8.1 (Berkeley) 6/14/93
68 */
69
70#include <sys/cdefs.h>
71__FBSDID("$FreeBSD: head/sys/kern/kern_acct.c 167389 2007-03-09 23:29:31Z jhb $");
71__FBSDID("$FreeBSD: head/sys/kern/kern_acct.c 169857 2007-05-22 06:51:38Z dds $");
72
73#include "opt_mac.h"
74
75#include <sys/param.h>
76#include <sys/systm.h>
77#include <sys/acct.h>
78#include <sys/fcntl.h>
79#include <sys/kernel.h>

--- 16 unchanged lines hidden (view full) ---

96
97#include <security/mac/mac_framework.h>
98
99/*
100 * The routines implemented in this file are described in:
101 * Leffler, et al.: The Design and Implementation of the 4.3BSD
102 * UNIX Operating System (Addison Welley, 1989)
103 * on pages 62-63.
72
73#include "opt_mac.h"
74
75#include <sys/param.h>
76#include <sys/systm.h>
77#include <sys/acct.h>
78#include <sys/fcntl.h>
79#include <sys/kernel.h>

--- 16 unchanged lines hidden (view full) ---

96
97#include <security/mac/mac_framework.h>
98
99/*
100 * The routines implemented in this file are described in:
101 * Leffler, et al.: The Design and Implementation of the 4.3BSD
102 * UNIX Operating System (Addison Welley, 1989)
103 * on pages 62-63.
104 * On May 2007 the historic 3 bits base 8 exponent, 13 bit fraction
105 * compt_t representation described in the above reference was replaced
106 * with that of IEEE-754 floats.
104 *
105 * Arguably, to simplify accounting operations, this mechanism should
106 * be replaced by one in which an accounting log file (similar to /dev/klog)
107 * is read by a user process, etc. However, that has its own problems.
108 */
109
107 *
108 * Arguably, to simplify accounting operations, this mechanism should
109 * be replaced by one in which an accounting log file (similar to /dev/klog)
110 * is read by a user process, etc. However, that has its own problems.
111 */
112
113/* Floating point definitions from <float.h>. */
114#define FLT_MANT_DIG 24 /* p */
115#define FLT_MAX_EXP 128 /* emax */
116
110/*
111 * Internal accounting functions.
112 * The former's operation is described in Leffler, et al., and the latter
113 * was provided by UCB with the 4.4BSD-Lite release
114 */
117/*
118 * Internal accounting functions.
119 * The former's operation is described in Leffler, et al., and the latter
120 * was provided by UCB with the 4.4BSD-Lite release
121 */
115static comp_t encode_comp_t(u_long, u_long);
122static uint32_t encode_timeval(struct timeval);
123static uint32_t encode_long(long);
116static void acctwatch(void);
117static void acct_thread(void *);
118static int acct_disable(struct thread *);
119
120/*
121 * Accounting vnode pointer, saved vnode pointer, and flags for each.
122 * acct_sx protects against changes to the active vnode and credentials
123 * while accounting records are being committed to disk.

--- 196 unchanged lines hidden (view full) ---

320 * Write out process accounting information, on process exit.
321 * Data to be written out is specified in Leffler, et al.
322 * and are enumerated below. (They're also noted in the system
323 * "acct.h" header file.)
324 */
325int
326acct_process(struct thread *td)
327{
124static void acctwatch(void);
125static void acct_thread(void *);
126static int acct_disable(struct thread *);
127
128/*
129 * Accounting vnode pointer, saved vnode pointer, and flags for each.
130 * acct_sx protects against changes to the active vnode and credentials
131 * while accounting records are being committed to disk.

--- 196 unchanged lines hidden (view full) ---

328 * Write out process accounting information, on process exit.
329 * Data to be written out is specified in Leffler, et al.
330 * and are enumerated below. (They're also noted in the system
331 * "acct.h" header file.)
332 */
333int
334acct_process(struct thread *td)
335{
328 struct acct acct;
336 struct acctv2 acct;
329 struct timeval ut, st, tmp;
330 struct plimit *newlim, *oldlim;
331 struct proc *p;
332 struct rusage *r;
333 int t, ret, vfslocked;
334
335 /*
336 * Lockless check of accounting condition before doing the hard

--- 21 unchanged lines hidden (view full) ---

358 */
359
360 PROC_LOCK(p);
361 /* (1) The name of the command that ran */
362 bcopy(p->p_comm, acct.ac_comm, sizeof acct.ac_comm);
363
364 /* (2) The amount of user and system time that was used */
365 calcru(p, &ut, &st);
337 struct timeval ut, st, tmp;
338 struct plimit *newlim, *oldlim;
339 struct proc *p;
340 struct rusage *r;
341 int t, ret, vfslocked;
342
343 /*
344 * Lockless check of accounting condition before doing the hard

--- 21 unchanged lines hidden (view full) ---

366 */
367
368 PROC_LOCK(p);
369 /* (1) The name of the command that ran */
370 bcopy(p->p_comm, acct.ac_comm, sizeof acct.ac_comm);
371
372 /* (2) The amount of user and system time that was used */
373 calcru(p, &ut, &st);
366 acct.ac_utime = encode_comp_t(ut.tv_sec, ut.tv_usec);
367 acct.ac_stime = encode_comp_t(st.tv_sec, st.tv_usec);
374 acct.ac_utime = encode_timeval(ut);
375 acct.ac_stime = encode_timeval(st);
368
369 /* (3) The elapsed time the command ran (and its starting time) */
370 tmp = boottime;
371 timevaladd(&tmp, &p->p_stats->p_start);
372 acct.ac_btime = tmp.tv_sec;
373 microuptime(&tmp);
374 timevalsub(&tmp, &p->p_stats->p_start);
376
377 /* (3) The elapsed time the command ran (and its starting time) */
378 tmp = boottime;
379 timevaladd(&tmp, &p->p_stats->p_start);
380 acct.ac_btime = tmp.tv_sec;
381 microuptime(&tmp);
382 timevalsub(&tmp, &p->p_stats->p_start);
375 acct.ac_etime = encode_comp_t(tmp.tv_sec, tmp.tv_usec);
383 acct.ac_etime = encode_timeval(tmp);
376
377 /* (4) The average amount of memory used */
378 r = &p->p_stats->p_ru;
379 tmp = ut;
380 timevaladd(&tmp, &st);
384
385 /* (4) The average amount of memory used */
386 r = &p->p_stats->p_ru;
387 tmp = ut;
388 timevaladd(&tmp, &st);
389 /* Convert tmp (i.e. u + s) into hz units to match ru_i*. */
381 t = tmp.tv_sec * hz + tmp.tv_usec / tick;
382 if (t)
390 t = tmp.tv_sec * hz + tmp.tv_usec / tick;
391 if (t)
383 acct.ac_mem = (r->ru_ixrss + r->ru_idrss + r->ru_isrss) / t;
392 acct.ac_mem = encode_long((r->ru_ixrss + r->ru_idrss +
393 + r->ru_isrss) / t);
384 else
385 acct.ac_mem = 0;
386
387 /* (5) The number of disk I/O operations done */
394 else
395 acct.ac_mem = 0;
396
397 /* (5) The number of disk I/O operations done */
388 acct.ac_io = encode_comp_t(r->ru_inblock + r->ru_oublock, 0);
398 acct.ac_io = encode_long(r->ru_inblock + r->ru_oublock);
389
390 /* (6) The UID and GID of the process */
391 acct.ac_uid = p->p_ucred->cr_ruid;
392 acct.ac_gid = p->p_ucred->cr_rgid;
393
394 /* (7) The terminal from which the process was started */
395 SESS_LOCK(p->p_session);
396 if ((p->p_flag & P_CONTROLT) && p->p_pgrp->pg_session->s_ttyp)
397 acct.ac_tty = dev2udev(p->p_pgrp->pg_session->s_ttyp->t_dev);
398 else
399 acct.ac_tty = NODEV;
400 SESS_UNLOCK(p->p_session);
401
402 /* (8) The boolean flags that tell how the process terminated, etc. */
399
400 /* (6) The UID and GID of the process */
401 acct.ac_uid = p->p_ucred->cr_ruid;
402 acct.ac_gid = p->p_ucred->cr_rgid;
403
404 /* (7) The terminal from which the process was started */
405 SESS_LOCK(p->p_session);
406 if ((p->p_flag & P_CONTROLT) && p->p_pgrp->pg_session->s_ttyp)
407 acct.ac_tty = dev2udev(p->p_pgrp->pg_session->s_ttyp->t_dev);
408 else
409 acct.ac_tty = NODEV;
410 SESS_UNLOCK(p->p_session);
411
412 /* (8) The boolean flags that tell how the process terminated, etc. */
403 acct.ac_flag = p->p_acflag;
413 acct.ac_flagx = p->p_acflag;
404 PROC_UNLOCK(p);
405
414 PROC_UNLOCK(p);
415
416 /* Setup ancillary structure fields. */
417 acct.ac_flagx |= ANVER;
418 acct.ac_zero = 0;
419 acct.ac_version = 2;
420 acct.ac_len = acct.ac_len2 = sizeof(acct);
421
406 /*
407 * Eliminate any file size rlimit.
408 */
409 newlim = lim_alloc();
410 PROC_LOCK(p);
411 oldlim = p->p_limit;
412 lim_copy(newlim, oldlim);
413 newlim->pl_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;

--- 9 unchanged lines hidden (view full) ---

423 ret = vn_rdwr(UIO_WRITE, acct_vp, (caddr_t)&acct, sizeof (acct),
424 (off_t)0, UIO_SYSSPACE, IO_APPEND|IO_UNIT, acct_cred, NOCRED,
425 (int *)0, td);
426 VFS_UNLOCK_GIANT(vfslocked);
427 sx_sunlock(&acct_sx);
428 return (ret);
429}
430
422 /*
423 * Eliminate any file size rlimit.
424 */
425 newlim = lim_alloc();
426 PROC_LOCK(p);
427 oldlim = p->p_limit;
428 lim_copy(newlim, oldlim);
429 newlim->pl_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;

--- 9 unchanged lines hidden (view full) ---

439 ret = vn_rdwr(UIO_WRITE, acct_vp, (caddr_t)&acct, sizeof (acct),
440 (off_t)0, UIO_SYSSPACE, IO_APPEND|IO_UNIT, acct_cred, NOCRED,
441 (int *)0, td);
442 VFS_UNLOCK_GIANT(vfslocked);
443 sx_sunlock(&acct_sx);
444 return (ret);
445}
446
447/* FLOAT_CONVERSION_START (Regression testing; don't remove this line.) */
448
449/* Convert timevals and longs into IEEE-754 bit patterns. */
450
451/* Mantissa mask (MSB is implied, so subtract 1). */
452#define MANT_MASK ((1 << (FLT_MANT_DIG - 1)) - 1)
453
431/*
454/*
432 * Encode_comp_t converts from ticks in seconds and microseconds
433 * to ticks in 1/AHZ seconds. The encoding is described in
434 * Leffler, et al., on page 63.
455 * We calculate integer values to a precision of approximately
456 * 28 bits.
457 * This is high-enough precision to fill the 24 float bits
458 * and low-enough to avoid overflowing the 32 int bits.
435 */
459 */
460#define CALC_BITS 28
436
461
437#define MANTSIZE 13 /* 13 bit mantissa. */
438#define EXPSIZE 3 /* Base 8 (3 bit) exponent. */
439#define MAXFRACT ((1 << MANTSIZE) - 1) /* Maximum fractional value. */
462/* log_2(1000000). */
463#define LOG2_1M 20
440
464
441static comp_t
442encode_comp_t(u_long s, u_long us)
465/*
466 * Convert the elements of a timeval into a 32-bit word holding
467 * the bits of a IEEE-754 float.
468 * The float value represents the timeval's value in microsecond units.
469 */
470static uint32_t
471encode_timeval(struct timeval tv)
443{
472{
444 int exp, rnd;
473 int log2_s;
474 int val, exp; /* Unnormalized value and exponent */
475 int norm_exp; /* Normalized exponent */
476 int shift;
445
477
446 exp = 0;
447 rnd = 0;
448 s *= AHZ;
449 s += us / (1000000 / AHZ); /* Maximize precision. */
450
451 while (s > MAXFRACT) {
452 rnd = s & (1 << (EXPSIZE - 1)); /* Round up? */
453 s >>= EXPSIZE; /* Base 8 exponent == 3 bit shift. */
454 exp++;
478 /*
479 * First calculate value and exponent to about CALC_BITS precision.
480 * Note that the following conditionals have been ordered so that
481 * the most common cases appear first.
482 */
483 if (tv.tv_sec == 0) {
484 if (tv.tv_usec == 0)
485 return (0);
486 exp = 0;
487 val = tv.tv_usec;
488 } else {
489 /*
490 * Calculate the value to a precision of approximately
491 * CALC_BITS.
492 */
493 log2_s = fls(tv.tv_sec) - 1;
494 if (log2_s + LOG2_1M < CALC_BITS) {
495 exp = 0;
496 val = 1000000 * tv.tv_sec + tv.tv_usec;
497 } else {
498 exp = log2_s + LOG2_1M - CALC_BITS;
499 val = (unsigned int)(((u_int64_t)1000000 * tv.tv_sec +
500 tv.tv_usec) >> exp);
501 }
455 }
502 }
503 /* Now normalize and pack the value into an IEEE-754 float. */
504 norm_exp = fls(val) - 1;
505 shift = FLT_MANT_DIG - norm_exp - 1;
506#ifdef ACCT_DEBUG
507 printf("val=%d exp=%d shift=%d log2(val)=%d\n",
508 val, exp, shift, norm_exp);
509 printf("exp=%x mant=%x\n", FLT_MAX_EXP - 1 + exp + norm_exp,
510 ((shift > 0 ? (val << shift) : (val >> -shift)) & MANT_MASK));
511#endif
512 return (((FLT_MAX_EXP - 1 + exp + norm_exp) << (FLT_MANT_DIG - 1)) |
513 ((shift > 0 ? val << shift : val >> -shift) & MANT_MASK));
514}
456
515
457 /* If we need to round up, do it (and handle overflow correctly). */
458 if (rnd && (++s > MAXFRACT)) {
459 s >>= EXPSIZE;
460 exp++;
461 }
516/*
517 * Convert a non-negative long value into the bit pattern of
518 * an IEEE-754 float value.
519 */
520static uint32_t
521encode_long(long val)
522{
523 int norm_exp; /* Normalized exponent */
524 int shift;
462
525
463 /* Clean it up and polish it off. */
464 exp <<= MANTSIZE; /* Shift the exponent into place */
465 exp += s; /* and add on the mantissa. */
466 return (exp);
526 KASSERT(val >= 0, ("encode_long: -ve value %ld", val));
527 if (val == 0)
528 return (0);
529 norm_exp = fls(val) - 1;
530 shift = FLT_MANT_DIG - norm_exp - 1;
531#ifdef ACCT_DEBUG
532 printf("val=%d shift=%d log2(val)=%d\n",
533 val, shift, norm_exp);
534 printf("exp=%x mant=%x\n", FLT_MAX_EXP - 1 + exp + norm_exp,
535 ((shift > 0 ? (val << shift) : (val >> -shift)) & MANT_MASK));
536#endif
537 return (((FLT_MAX_EXP - 1 + norm_exp) << (FLT_MANT_DIG - 1)) |
538 ((shift > 0 ? val << shift : val >> -shift) & MANT_MASK));
467}
468
539}
540
541/* FLOAT_CONVERSION_END (Regression testing; don't remove this line.) */
542
469/*
470 * Periodically check the filesystem to see if accounting
471 * should be turned on or off. Beware the case where the vnode
472 * has been vgone()'d out from underneath us, e.g. when the file
473 * system containing the accounting file has been forcibly unmounted.
474 */
475/* ARGSUSED */
476static void

--- 101 unchanged lines hidden ---
543/*
544 * Periodically check the filesystem to see if accounting
545 * should be turned on or off. Beware the case where the vnode
546 * has been vgone()'d out from underneath us, e.g. when the file
547 * system containing the accounting file has been forcibly unmounted.
548 */
549/* ARGSUSED */
550static void

--- 101 unchanged lines hidden ---