1f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan/*
2f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan * tsacct.c - System accounting over taskstats interface
3f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan *
4f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan * Copyright (C) Jay Lan,	<jlan@sgi.com>
5f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan *
6f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan *
7f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan * This program is free software; you can redistribute it and/or modify
8f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan * it under the terms of the GNU General Public License as published by
9f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan * the Free Software Foundation; either version 2 of the License, or
10f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan * (at your option) any later version.
11f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan *
12f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan * This program is distributed in the hope that it will be useful,
13f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan * but WITHOUT ANY WARRANTY; without even the implied warranty of
14f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan * GNU General Public License for more details.
16f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan *
17f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan */
18f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan
19f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan#include <linux/kernel.h>
20f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan#include <linux/sched.h>
21f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan#include <linux/tsacct_kern.h>
22f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan#include <linux/acct.h>
23db5fed26b2e0beed939b773dd5896077a1794d65Jay Lan#include <linux/jiffies.h>
24d559db086ff5be9bcc259e5aa50bf3d881eaf1d1KAMEZAWA Hiroyuki#include <linux/mm.h>
25f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan
26f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan/*
27f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan * fill in basic accounting fields
28f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan */
294bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biedermanvoid bacct_add_tsk(struct user_namespace *user_ns,
304bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biederman		   struct pid_namespace *pid_ns,
314bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biederman		   struct taskstats *stats, struct task_struct *tsk)
32f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan{
33c69e8d9c01db2adc503464993c358901c9af9de4David Howells	const struct cred *tcred;
346fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker	cputime_t utime, stime, utimescaled, stimescaled;
35ccbf62d8a284cf181ac28c8e8407dd077d90dd4bThomas Gleixner	u64 delta;
36f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan
37f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan	BUILD_BUG_ON(TS_COMM_LEN < TASK_COMM_LEN);
38f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan
39ccbf62d8a284cf181ac28c8e8407dd077d90dd4bThomas Gleixner	/* calculate task elapsed time in nsec */
40ccbf62d8a284cf181ac28c8e8407dd077d90dd4bThomas Gleixner	delta = ktime_get_ns() - tsk->start_time;
41ccbf62d8a284cf181ac28c8e8407dd077d90dd4bThomas Gleixner	/* Convert to micro seconds */
42ccbf62d8a284cf181ac28c8e8407dd077d90dd4bThomas Gleixner	do_div(delta, NSEC_PER_USEC);
43ccbf62d8a284cf181ac28c8e8407dd077d90dd4bThomas Gleixner	stats->ac_etime = delta;
44ccbf62d8a284cf181ac28c8e8407dd077d90dd4bThomas Gleixner	/* Convert to seconds for btime */
45ccbf62d8a284cf181ac28c8e8407dd077d90dd4bThomas Gleixner	do_div(delta, USEC_PER_SEC);
46ccbf62d8a284cf181ac28c8e8407dd077d90dd4bThomas Gleixner	stats->ac_btime = get_seconds() - delta;
47f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan	if (thread_group_leader(tsk)) {
48f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan		stats->ac_exitcode = tsk->exit_code;
49f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan		if (tsk->flags & PF_FORKNOEXEC)
50f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan			stats->ac_flag |= AFORK;
51f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan	}
52f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan	if (tsk->flags & PF_SUPERPRIV)
53f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan		stats->ac_flag |= ASU;
54f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan	if (tsk->flags & PF_DUMPCORE)
55f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan		stats->ac_flag |= ACORE;
56f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan	if (tsk->flags & PF_SIGNALED)
57f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan		stats->ac_flag |= AXSIG;
58f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan	stats->ac_nice	 = task_nice(tsk);
59f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan	stats->ac_sched	 = tsk->policy;
604bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biederman	stats->ac_pid	 = task_pid_nr_ns(tsk, pid_ns);
6105d5bcd60e8202e5c7b28cf61186043a4d612623Oleg Nesterov	rcu_read_lock();
62c69e8d9c01db2adc503464993c358901c9af9de4David Howells	tcred = __task_cred(tsk);
634bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biederman	stats->ac_uid	 = from_kuid_munged(user_ns, tcred->uid);
644bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biederman	stats->ac_gid	 = from_kgid_munged(user_ns, tcred->gid);
6505d5bcd60e8202e5c7b28cf61186043a4d612623Oleg Nesterov	stats->ac_ppid	 = pid_alive(tsk) ?
664bd6e32acec66c55c6c1af4672f3216b2ac88e35Eric W. Biederman		task_tgid_nr_ns(rcu_dereference(tsk->real_parent), pid_ns) : 0;
6705d5bcd60e8202e5c7b28cf61186043a4d612623Oleg Nesterov	rcu_read_unlock();
686fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker
696fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker	task_cputime(tsk, &utime, &stime);
706fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker	stats->ac_utime = cputime_to_usecs(utime);
716fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker	stats->ac_stime = cputime_to_usecs(stime);
726fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker
736fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker	task_cputime_scaled(tsk, &utimescaled, &stimescaled);
746fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker	stats->ac_utimescaled = cputime_to_usecs(utimescaled);
756fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker	stats->ac_stimescaled = cputime_to_usecs(stimescaled);
766fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker
77f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan	stats->ac_minflt = tsk->min_flt;
78f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan	stats->ac_majflt = tsk->maj_flt;
79f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan
80f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan	strncpy(stats->ac_comm, tsk->comm, sizeof(stats->ac_comm));
81f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan}
82f3cef7a99469afc159fec3a61b42dc7ca5b6824fJay Lan
839acc1853519a0473620d424105f9d49ea5b4e62eJay Lan
849acc1853519a0473620d424105f9d49ea5b4e62eJay Lan#ifdef CONFIG_TASK_XACCT
85db5fed26b2e0beed939b773dd5896077a1794d65Jay Lan
86db5fed26b2e0beed939b773dd5896077a1794d65Jay Lan#define KB 1024
87db5fed26b2e0beed939b773dd5896077a1794d65Jay Lan#define MB (1024*KB)
8858c3c3aa01b455ecb99d61ce73f1444274af696bLinus Torvalds#define KB_MASK (~(KB-1))
899acc1853519a0473620d424105f9d49ea5b4e62eJay Lan/*
909acc1853519a0473620d424105f9d49ea5b4e62eJay Lan * fill in extended accounting fields
919acc1853519a0473620d424105f9d49ea5b4e62eJay Lan */
929acc1853519a0473620d424105f9d49ea5b4e62eJay Lanvoid xacct_add_tsk(struct taskstats *stats, struct task_struct *p)
939acc1853519a0473620d424105f9d49ea5b4e62eJay Lan{
94f0ec1aaf54caddd21c259aea8b2ecfbde4ee4fb9Oleg Nesterov	struct mm_struct *mm;
95f0ec1aaf54caddd21c259aea8b2ecfbde4ee4fb9Oleg Nesterov
9649b5cf34727a6c1be1568ab28e89a2d9a6bf51e0Jonathan Lim	/* convert pages-usec to Mbyte-usec */
9749b5cf34727a6c1be1568ab28e89a2d9a6bf51e0Jonathan Lim	stats->coremem = p->acct_rss_mem1 * PAGE_SIZE / MB;
9849b5cf34727a6c1be1568ab28e89a2d9a6bf51e0Jonathan Lim	stats->virtmem = p->acct_vm_mem1 * PAGE_SIZE / MB;
99f0ec1aaf54caddd21c259aea8b2ecfbde4ee4fb9Oleg Nesterov	mm = get_task_mm(p);
100f0ec1aaf54caddd21c259aea8b2ecfbde4ee4fb9Oleg Nesterov	if (mm) {
101db5fed26b2e0beed939b773dd5896077a1794d65Jay Lan		/* adjust to KB unit */
102901608d9045146aec6f14a7777ea4b1501c379f0Oleg Nesterov		stats->hiwater_rss   = get_mm_hiwater_rss(mm) * PAGE_SIZE / KB;
103901608d9045146aec6f14a7777ea4b1501c379f0Oleg Nesterov		stats->hiwater_vm    = get_mm_hiwater_vm(mm)  * PAGE_SIZE / KB;
104f0ec1aaf54caddd21c259aea8b2ecfbde4ee4fb9Oleg Nesterov		mmput(mm);
1059acc1853519a0473620d424105f9d49ea5b4e62eJay Lan	}
10658c3c3aa01b455ecb99d61ce73f1444274af696bLinus Torvalds	stats->read_char	= p->ioac.rchar & KB_MASK;
10758c3c3aa01b455ecb99d61ce73f1444274af696bLinus Torvalds	stats->write_char	= p->ioac.wchar & KB_MASK;
10858c3c3aa01b455ecb99d61ce73f1444274af696bLinus Torvalds	stats->read_syscalls	= p->ioac.syscr & KB_MASK;
10958c3c3aa01b455ecb99d61ce73f1444274af696bLinus Torvalds	stats->write_syscalls	= p->ioac.syscw & KB_MASK;
1104a7864ca638e0a38307962ee8ef122822a351b65Andrew Morton#ifdef CONFIG_TASK_IO_ACCOUNTING
11158c3c3aa01b455ecb99d61ce73f1444274af696bLinus Torvalds	stats->read_bytes	= p->ioac.read_bytes & KB_MASK;
11258c3c3aa01b455ecb99d61ce73f1444274af696bLinus Torvalds	stats->write_bytes	= p->ioac.write_bytes & KB_MASK;
11358c3c3aa01b455ecb99d61ce73f1444274af696bLinus Torvalds	stats->cancelled_write_bytes = p->ioac.cancelled_write_bytes & KB_MASK;
1144a7864ca638e0a38307962ee8ef122822a351b65Andrew Morton#else
1154a7864ca638e0a38307962ee8ef122822a351b65Andrew Morton	stats->read_bytes	= 0;
1164a7864ca638e0a38307962ee8ef122822a351b65Andrew Morton	stats->write_bytes	= 0;
1174a7864ca638e0a38307962ee8ef122822a351b65Andrew Morton	stats->cancelled_write_bytes = 0;
1184a7864ca638e0a38307962ee8ef122822a351b65Andrew Morton#endif
1199acc1853519a0473620d424105f9d49ea5b4e62eJay Lan}
120db5fed26b2e0beed939b773dd5896077a1794d65Jay Lan#undef KB
121db5fed26b2e0beed939b773dd5896077a1794d65Jay Lan#undef MB
1228f0ab5147951267134612570604cf8341901a80cJay Lan
1236fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbeckerstatic void __acct_update_integrals(struct task_struct *tsk,
1246fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker				    cputime_t utime, cputime_t stime)
1258f0ab5147951267134612570604cf8341901a80cJay Lan{
1268f0ab5147951267134612570604cf8341901a80cJay Lan	if (likely(tsk->mm)) {
12749b5cf34727a6c1be1568ab28e89a2d9a6bf51e0Jonathan Lim		cputime_t time, dtime;
12849b5cf34727a6c1be1568ab28e89a2d9a6bf51e0Jonathan Lim		struct timeval value;
1296d5b5acca9e566515ef3f1ed617e7295c4f94345Heiko Carstens		unsigned long flags;
13049b5cf34727a6c1be1568ab28e89a2d9a6bf51e0Jonathan Lim		u64 delta;
13149b5cf34727a6c1be1568ab28e89a2d9a6bf51e0Jonathan Lim
1326d5b5acca9e566515ef3f1ed617e7295c4f94345Heiko Carstens		local_irq_save(flags);
1336fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker		time = stime + utime;
134648616343cdbe904c585a6c12e323d3b3c72e46fMartin Schwidefsky		dtime = time - tsk->acct_timexpd;
13549b5cf34727a6c1be1568ab28e89a2d9a6bf51e0Jonathan Lim		jiffies_to_timeval(cputime_to_jiffies(dtime), &value);
13649b5cf34727a6c1be1568ab28e89a2d9a6bf51e0Jonathan Lim		delta = value.tv_sec;
13749b5cf34727a6c1be1568ab28e89a2d9a6bf51e0Jonathan Lim		delta = delta * USEC_PER_SEC + value.tv_usec;
1388f0ab5147951267134612570604cf8341901a80cJay Lan
1398f0ab5147951267134612570604cf8341901a80cJay Lan		if (delta == 0)
1406d5b5acca9e566515ef3f1ed617e7295c4f94345Heiko Carstens			goto out;
14149b5cf34727a6c1be1568ab28e89a2d9a6bf51e0Jonathan Lim		tsk->acct_timexpd = time;
1428f0ab5147951267134612570604cf8341901a80cJay Lan		tsk->acct_rss_mem1 += delta * get_mm_rss(tsk->mm);
1438f0ab5147951267134612570604cf8341901a80cJay Lan		tsk->acct_vm_mem1 += delta * tsk->mm->total_vm;
1446d5b5acca9e566515ef3f1ed617e7295c4f94345Heiko Carstens	out:
1456d5b5acca9e566515ef3f1ed617e7295c4f94345Heiko Carstens		local_irq_restore(flags);
1468f0ab5147951267134612570604cf8341901a80cJay Lan	}
1478f0ab5147951267134612570604cf8341901a80cJay Lan}
1488f0ab5147951267134612570604cf8341901a80cJay Lan
1498f0ab5147951267134612570604cf8341901a80cJay Lan/**
1506fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker * acct_update_integrals - update mm integral fields in task_struct
1516fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker * @tsk: task_struct for accounting
1526fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker */
1536fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbeckervoid acct_update_integrals(struct task_struct *tsk)
1546fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker{
1556fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker	cputime_t utime, stime;
1566fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker
1576fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker	task_cputime(tsk, &utime, &stime);
1586fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker	__acct_update_integrals(tsk, utime, stime);
1596fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker}
1606fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker
1616fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker/**
1626fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker * acct_account_cputime - update mm integral after cputime update
1636fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker * @tsk: task_struct for accounting
1646fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker */
1656fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbeckervoid acct_account_cputime(struct task_struct *tsk)
1666fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker{
1676fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker	__acct_update_integrals(tsk, tsk->utime, tsk->stime);
1686fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker}
1696fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker
1706fac4829ce0ef9b7f24369086ce5f0e9f38d37bcFrederic Weisbecker/**
1718f0ab5147951267134612570604cf8341901a80cJay Lan * acct_clear_integrals - clear the mm integral fields in task_struct
1728f0ab5147951267134612570604cf8341901a80cJay Lan * @tsk: task_struct whose accounting fields are cleared
1738f0ab5147951267134612570604cf8341901a80cJay Lan */
1748f0ab5147951267134612570604cf8341901a80cJay Lanvoid acct_clear_integrals(struct task_struct *tsk)
1758f0ab5147951267134612570604cf8341901a80cJay Lan{
17649b5cf34727a6c1be1568ab28e89a2d9a6bf51e0Jonathan Lim	tsk->acct_timexpd = 0;
1778f0ab5147951267134612570604cf8341901a80cJay Lan	tsk->acct_rss_mem1 = 0;
1788f0ab5147951267134612570604cf8341901a80cJay Lan	tsk->acct_vm_mem1 = 0;
1798f0ab5147951267134612570604cf8341901a80cJay Lan}
1809acc1853519a0473620d424105f9d49ea5b4e62eJay Lan#endif
181