79#include <sys/kernel.h>
80#include <sys/kthread.h>
81#include <sys/limits.h>
83#include <sys/malloc.h>
89#include <sys/resourcevar.h>
92#include <sys/sysctl.h>
93#include <sys/sysent.h>
94#include <sys/syslog.h>
95#include <sys/sysproto.h>
99#include <security/mac/mac_framework.h>
102 sizeof(
struct acctv2) - offsetof(
struct acctv2, ac_trailer),
"trailer");
104 sizeof(
struct acctv2) - offsetof(
struct acctv2, ac_len2),
"len2");
121#define FLT_MANT_DIG 24
122#define FLT_MAX_EXP 128
154#define ACCT_RUNNING 1
155#define ACCT_EXITREQ 2
162 &
acctsuspend, 0,
"percentage of free disk space below which accounting stops");
166 &
acctresume, 0,
"percentage of free disk space above which accounting resumes");
176 error = SYSCTL_OUT(req, &
acctchkfreq,
sizeof(
int));
177 if (error || req->newptr == NULL)
181 error = SYSCTL_IN(req, &
value,
sizeof(
int));
190 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, &
acctchkfreq, 0,
192 "frequency for checking the free space");
195 "Accounting configured or not");
198 "Accounting suspended or not");
208 int error,
flags, replacing;
218 if (uap->path != NULL) {
219 NDINIT(&nd, LOOKUP, NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
221 flags = FWRITE | O_APPEND;
225 NDFREE(&nd, NDF_ONLY_PNBUF);
227 error = mac_system_check_acct(td->td_ucred, nd.ni_vp);
229 VOP_UNLOCK(nd.ni_vp);
234 VOP_UNLOCK(nd.ni_vp);
235 if (nd.ni_vp->v_type != VREG) {
241 error = mac_system_check_acct(td->td_ucred, NULL);
258 replacing = (
acct_vp != NULL && uap->path != NULL);
269 if (uap->path == NULL) {
298 log(LOG_NOTICE,
"Unable to start accounting thread\n");
305 log(LOG_NOTICE,
"Accounting enabled\n");
318 sx_assert(&
acct_sx, SX_XLOCKED);
326 log(LOG_NOTICE,
"Accounting disabled\n");
340 struct timeval ut,
st, tmp;
352 memset(&acct, 0,
sizeof(acct));
367 td->td_pflags2 |= TDP2_ACCT;
377 if ((p->p_flag & P_CONTROLT) && p->p_pgrp->pg_session->s_ttyp)
378 acct.ac_tty =
tty_udev(p->p_pgrp->pg_session->s_ttyp);
384 bcopy(p->p_comm, acct.ac_comm,
sizeof acct.ac_comm);
394 acct.ac_btime = tmp.tv_sec;
403 t = tmp.tv_sec *
hz + tmp.tv_usec /
tick;
405 acct.ac_mem =
encode_long((ru.ru_ixrss + ru.ru_idrss +
411 acct.ac_io =
encode_long(ru.ru_inblock + ru.ru_oublock);
414 acct.ac_uid = p->p_ucred->cr_ruid;
415 acct.ac_gid = p->p_ucred->cr_rgid;
418 acct.ac_flagx = p->p_acflag;
423 acct.ac_flagx |= ANVER;
426 acct.ac_len = acct.ac_len2 =
sizeof(acct);
432 (off_t)0, UIO_SYSSPACE, IO_APPEND|IO_UNIT,
acct_cred, NOCRED,
435 td->td_pflags2 &= ~TDP2_ACCT;
444#define MANT_MASK ((1 << (FLT_MANT_DIG - 1)) - 1)
475 if (tv.tv_sec == 0) {
485 log2_s = fls(tv.tv_sec) - 1;
488 val = 1000000 * tv.tv_sec + tv.tv_usec;
491 val = (
unsigned int)(((uint64_t)1000000 * tv.tv_sec +
496 norm_exp = fls(val) - 1;
499 printf(
"val=%d exp=%d shift=%d log2(val)=%d\n",
500 val, exp, shift, norm_exp);
502 ((shift > 0 ? (val << shift) : (val >> -shift)) &
MANT_MASK));
505 ((shift > 0 ? val << shift : val >> -shift) &
MANT_MASK));
522 "encode_long: negative value %ld in accounting record\n",
526 norm_exp = fls(val) - 1;
529 printf(
"val=%d shift=%d log2(val)=%d\n",
530 val, shift, norm_exp);
532 ((shift > 0 ? (val << shift) : (val >> -shift)) &
MANT_MASK));
535 ((shift > 0 ? val << shift : val >> -shift) &
MANT_MASK));
552 sx_assert(&
acct_sx, SX_XLOCKED);
578 sp =
malloc(
sizeof(
struct statfs), M_STATFS, M_WAITOK);
579 if (VFS_STATFS(
acct_vp->v_mount, sp) < 0) {
584 if (sp->f_bavail > (int64_t)(
acctresume * sp->f_blocks /
587 log(LOG_NOTICE,
"Accounting resumed\n");
590 if (sp->f_bavail <= (int64_t)(
acctsuspend * sp->f_blocks /
593 log(LOG_NOTICE,
"Accounting suspended\n");
610 thread_lock(curthread);
612 thread_unlock(curthread);
static int sysctl_acct_chkfreq(SYSCTL_HANDLER_ARGS)
SX_SYSINIT(acct, &acct_sx, "acct_sx")
static void acct_thread(void *)
SYSCTL_PROC(_kern, OID_AUTO, acct_chkfreq, CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_MPSAFE, &acctchkfreq, 0, sysctl_acct_chkfreq, "I", "frequency for checking the free space")
static int acct_suspended
static uint32_t encode_long(long)
static struct ucred * acct_cred
SYSCTL_INT(_kern, OID_AUTO, acct_suspend, CTLFLAG_RW, &acctsuspend, 0, "percentage of free disk space below which accounting stops")
static int acct_disable(struct thread *, int)
static struct vnode * acct_vp
static uint32_t encode_timeval(struct timeval)
int sys_acct(struct thread *td, struct acct_args *uap)
_Static_assert(sizeof(struct acctv3) - offsetof(struct acctv3, ac_trailer)==sizeof(struct acctv2) - offsetof(struct acctv2, ac_trailer), "trailer")
int acct_process(struct thread *td)
static void acctwatch(void)
static int acct_configured
static struct bt_table st
int kproc_create(void(*func)(void *), void *arg, struct proc **newpp, int flags, int pages, const char *fmt,...)
void kproc_exit(int ecode)
void *() malloc(size_t size, struct malloc_type *mtp, int flags)
void free(void *addr, struct malloc_type *mtp)
int priv_check(struct thread *td, int priv)
struct sx __exclusive_cache_line proctree_lock
struct ucred * crhold(struct ucred *cr)
void crfree(struct ucred *cr)
void rufetchcalc(struct proc *p, struct rusage *ru, struct timeval *up, struct timeval *sp)
void wakeup(const void *ident)
void getboottime(struct timeval *boottime)
void microuptime(struct timeval *tvp)
void timevaladd(struct timeval *t1, const struct timeval *t2)
void timevalsub(struct timeval *t1, const struct timeval *t2)
void sched_prio(struct thread *td, u_char prio)
int printf(const char *fmt,...)
void log(int level, const char *fmt,...)
dev_t tty_udev(struct tty *tp)
void() NDFREE(struct nameidata *ndp, const u_int flags)
int vn_rdwr(enum uio_rw rw, struct vnode *vp, void *base, int len, off_t offset, enum uio_seg segflg, int ioflg, struct ucred *active_cred, struct ucred *file_cred, ssize_t *aresid, struct thread *td)
int vn_open(struct nameidata *ndp, int *flagp, int cmode, struct file *fp)
int vn_close(struct vnode *vp, int flags, struct ucred *file_cred, struct thread *td)