The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/bsd/kern/kern_acct.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
   26 /*-
   27  * Copyright (c) 1982, 1986, 1989, 1993
   28  *      The Regents of the University of California.  All rights reserved.
   29  * (c) UNIX System Laboratories, Inc.
   30  * All or some portions of this file are derived from material licensed
   31  * to the University of California by American Telephone and Telegraph
   32  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   33  * the permission of UNIX System Laboratories, Inc.
   34  *
   35  * Redistribution and use in source and binary forms, with or without
   36  * modification, are permitted provided that the following conditions
   37  * are met:
   38  * 1. Redistributions of source code must retain the above copyright
   39  *    notice, this list of conditions and the following disclaimer.
   40  * 2. Redistributions in binary form must reproduce the above copyright
   41  *    notice, this list of conditions and the following disclaimer in the
   42  *    documentation and/or other materials provided with the distribution.
   43  * 3. All advertising materials mentioning features or use of this software
   44  *    must display the following acknowledgement:
   45  *      This product includes software developed by the University of
   46  *      California, Berkeley and its contributors.
   47  * 4. Neither the name of the University nor the names of its contributors
   48  *    may be used to endorse or promote products derived from this software
   49  *    without specific prior written permission.
   50  *
   51  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   52  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   53  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   54  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   55  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   56  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   57  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   58  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   59  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   60  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   61  * SUCH DAMAGE.
   62  *
   63  *      @(#)kern_acct.c 8.1 (Berkeley) 6/14/93
   64  */
   65 /* HISTORY
   66  * 08-May-95  Mac Gillon (mgillon) at NeXT
   67  *      Purged old history
   68  *      New version based on 4.4
   69  */
   70 
   71 
   72 #include <sys/param.h>
   73 #include <sys/proc.h>
   74 #include <sys/mount.h>
   75 #include <sys/vnode.h>
   76 #include <sys/file.h>
   77 #include <sys/syslog.h>
   78 #include <sys/kernel.h>
   79 #include <sys/namei.h>
   80 #include <sys/errno.h>
   81 #include <sys/acct.h>
   82 #include <sys/resourcevar.h>
   83 #include <sys/ioctl.h>
   84 #include <sys/tty.h>
   85 
   86 /*
   87  * The routines implemented in this file are described in:
   88  *      Leffler, et al.: The Design and Implementation of the 4.3BSD
   89  *          UNIX Operating System (Addison Welley, 1989)
   90  * on pages 62-63.
   91  *
   92  * Arguably, to simplify accounting operations, this mechanism should
   93  * be replaced by one in which an accounting log file (similar to /dev/klog)
   94  * is read by a user process, etc.  However, that has its own problems.
   95  */
   96 
   97 /*
   98  * Internal accounting functions.
   99  * The former's operation is described in Leffler, et al., and the latter
  100  * was provided by UCB with the 4.4BSD-Lite release
  101  */
  102 comp_t  encode_comp_t __P((u_long, u_long));
  103 void    acctwatch __P((void *));
  104 void    acctwatch_funnel __P((void *));
  105 
  106 /*
  107  * Accounting vnode pointer, and saved vnode pointer.
  108  */
  109 struct  vnode *acctp;
  110 struct  vnode *savacctp;
  111 
  112 /*
  113  * Values associated with enabling and disabling accounting
  114  */
  115 int     acctsuspend = 2;        /* stop accounting when < 2% free space left */
  116 int     acctresume = 4;         /* resume when free space risen to > 4% */
  117 int     acctchkfreq = 15;       /* frequency (in seconds) to check space */
  118 
  119 /*
  120  * Accounting system call.  Written based on the specification and
  121  * previous implementation done by Mark Tinguely.
  122  */
  123 struct acct_args {
  124         char    *path;
  125 };
  126 acct(p, uap, retval)
  127         struct proc *p;
  128         struct acct_args *uap;
  129         int *retval;
  130 {
  131         struct nameidata nd;
  132         int error;
  133 
  134         /* Make sure that the caller is root. */
  135         if (error = suser(p->p_ucred, &p->p_acflag))
  136                 return (error);
  137 
  138         /*
  139          * If accounting is to be started to a file, open that file for
  140          * writing and make sure it's a 'normal'.
  141          */
  142         if (uap->path != NULL) {
  143                 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, p);
  144                 if (error = vn_open(&nd, FWRITE, 0))
  145                         return (error);
  146                 VOP_UNLOCK(nd.ni_vp, 0, p);
  147                 if (nd.ni_vp->v_type != VREG) {
  148                         vn_close(nd.ni_vp, FWRITE, p->p_ucred, p);
  149                         return (EACCES);
  150                 }
  151         }
  152 
  153         /*
  154          * If accounting was previously enabled, kill the old space-watcher,
  155          * close the file, and (if no new file was specified, leave).
  156          */
  157         if (acctp != NULLVP || savacctp != NULLVP) {
  158                 untimeout(acctwatch_funnel, NULL);
  159                 error = vn_close((acctp != NULLVP ? acctp : savacctp), FWRITE,
  160                     p->p_ucred, p);
  161                 acctp = savacctp = NULLVP;
  162         }
  163         if (uap->path == NULL)
  164                 return (error);
  165 
  166         /*
  167          * Save the new accounting file vnode, and schedule the new
  168          * free space watcher.
  169          */
  170         acctp = nd.ni_vp;
  171         acctwatch(NULL);
  172         return (error);
  173 }
  174 
  175 /*
  176  * Write out process accounting information, on process exit.
  177  * Data to be written out is specified in Leffler, et al.
  178  * and are enumerated below.  (They're also noted in the system
  179  * "acct.h" header file.)
  180  */
  181 acct_process(p)
  182         struct proc *p;
  183 {
  184         struct acct acct;
  185         struct rusage *r;
  186         struct timeval ut, st, tmp;
  187         int s, t;
  188         struct vnode *vp;
  189 
  190         /* If accounting isn't enabled, don't bother */
  191         vp = acctp;
  192         if (vp == NULLVP)
  193                 return (0);
  194 
  195         /*
  196          * Get process accounting information.
  197          */
  198 
  199         /* (1) The name of the command that ran */
  200         bcopy(p->p_comm, acct.ac_comm, sizeof acct.ac_comm);
  201 
  202         /* (2) The amount of user and system time that was used */
  203         calcru(p, &ut, &st, NULL);
  204         acct.ac_utime = encode_comp_t(ut.tv_sec, ut.tv_usec);
  205         acct.ac_stime = encode_comp_t(st.tv_sec, st.tv_usec);
  206 
  207         /* (3) The elapsed time the commmand ran (and its starting time) */
  208         acct.ac_btime = p->p_stats->p_start.tv_sec;
  209         s = splclock();
  210         tmp = time;
  211         splx(s);
  212         timevalsub(&tmp, &p->p_stats->p_start);
  213         acct.ac_etime = encode_comp_t(tmp.tv_sec, tmp.tv_usec);
  214 
  215         /* (4) The average amount of memory used */
  216         r = &p->p_stats->p_ru;
  217         tmp = ut;
  218         timevaladd(&tmp, &st);
  219         t = tmp.tv_sec * hz + tmp.tv_usec / tick;
  220         if (t)
  221                 acct.ac_mem = (r->ru_ixrss + r->ru_idrss + r->ru_isrss) / t;
  222         else
  223                 acct.ac_mem = 0;
  224 
  225         /* (5) The number of disk I/O operations done */
  226         acct.ac_io = encode_comp_t(r->ru_inblock + r->ru_oublock, 0);
  227 
  228         /* (6) The UID and GID of the process */
  229         acct.ac_uid = p->p_cred->p_ruid;
  230         acct.ac_gid = p->p_cred->p_rgid;
  231 
  232         /* (7) The terminal from which the process was started */
  233         if ((p->p_flag & P_CONTROLT) && p->p_pgrp->pg_session->s_ttyp)
  234                 acct.ac_tty = p->p_pgrp->pg_session->s_ttyp->t_dev;
  235         else
  236                 acct.ac_tty = NODEV;
  237 
  238         /* (8) The boolean flags that tell how the process terminated, etc. */
  239         acct.ac_flag = p->p_acflag;
  240 
  241         /*
  242          * Now, just write the accounting information to the file.
  243          */
  244         VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
  245         return (vn_rdwr(UIO_WRITE, vp, (caddr_t)&acct, sizeof (acct),
  246             (off_t)0, UIO_SYSSPACE, IO_APPEND|IO_UNIT, p->p_ucred,
  247             (int *)0, p));
  248 }
  249 
  250 /*
  251  * Encode_comp_t converts from ticks in seconds and microseconds
  252  * to ticks in 1/AHZ seconds.  The encoding is described in
  253  * Leffler, et al., on page 63.
  254  */
  255 
  256 #define MANTSIZE        13                      /* 13 bit mantissa. */
  257 #define EXPSIZE         3                       /* Base 8 (3 bit) exponent. */
  258 #define MAXFRACT        ((1 << MANTSIZE) - 1)   /* Maximum fractional value. */
  259 
  260 comp_t
  261 encode_comp_t(s, us)
  262         u_long s, us;
  263 {
  264         int exp, rnd;
  265 
  266         exp = 0;
  267         rnd = 0;
  268         s *= AHZ;
  269         s += us / (1000000 / AHZ);      /* Maximize precision. */
  270 
  271         while (s > MAXFRACT) {
  272         rnd = s & (1 << (EXPSIZE - 1)); /* Round up? */
  273                 s >>= EXPSIZE;          /* Base 8 exponent == 3 bit shift. */
  274                 exp++;
  275         }
  276 
  277         /* If we need to round up, do it (and handle overflow correctly). */
  278         if (rnd && (++s > MAXFRACT)) {
  279                 s >>= EXPSIZE;
  280                 exp++;
  281         }
  282 
  283         /* Clean it up and polish it off. */
  284         exp <<= MANTSIZE;               /* Shift the exponent into place */
  285         exp += s;                       /* and add on the mantissa. */
  286         return (exp);
  287 }
  288 
  289 void
  290 acctwatch_funnel(a)
  291         void *a;
  292 {
  293         thread_funnel_set(kernel_flock, TRUE);
  294         acctwatch(a);
  295         thread_funnel_set(kernel_flock, FALSE);
  296 }
  297 
  298 
  299 /*
  300  * Periodically check the file system to see if accounting
  301  * should be turned on or off.  Beware the case where the vnode
  302  * has been vgone()'d out from underneath us, e.g. when the file
  303  * system containing the accounting file has been forcibly unmounted.
  304  */
  305 /* ARGSUSED */
  306 void
  307 acctwatch(a)
  308         void *a;
  309 {
  310         struct statfs sb;
  311 
  312         if (savacctp != NULLVP) {
  313                 if (savacctp->v_type == VBAD) {
  314                         (void) vn_close(savacctp, FWRITE, NOCRED, NULL);
  315                         savacctp = NULLVP;
  316                         return;
  317                 }
  318                 (void)VFS_STATFS(savacctp->v_mount, &sb, (struct proc *)0);
  319                 if (sb.f_bavail > acctresume * sb.f_blocks / 100) {
  320                         acctp = savacctp;
  321                         savacctp = NULLVP;
  322                         log(LOG_NOTICE, "Accounting resumed\n");
  323                 }
  324         } else if (acctp != NULLVP) {
  325                 if (acctp->v_type == VBAD) {
  326                         (void) vn_close(acctp, FWRITE, NOCRED, NULL);
  327                         acctp = NULLVP;
  328                         return;
  329                 }
  330                 (void)VFS_STATFS(acctp->v_mount, &sb, (struct proc *)0);
  331                 if (sb.f_bavail <= acctsuspend * sb.f_blocks / 100) {
  332                         savacctp = acctp;
  333                         acctp = NULLVP;
  334                         log(LOG_NOTICE, "Accounting suspended\n");
  335                 }
  336         } else {
  337                 return;
  338         }
  339         
  340         timeout(acctwatch_funnel, NULL, acctchkfreq * hz);
  341 }

Cache object: 6ebefefe24a123c407a4055e424c6336


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.