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 --- |