2006-10-01 10:28:55 +04:00
/*
* tsacct . c - System accounting over taskstats interface
*
* Copyright ( C ) Jay Lan , < jlan @ sgi . com >
*
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
*/
# include <linux/kernel.h>
# include <linux/sched.h>
# include <linux/tsacct_kern.h>
# include <linux/acct.h>
2006-10-01 10:29:00 +04:00
# include <linux/jiffies.h>
2010-03-06 00:41:39 +03:00
# include <linux/mm.h>
2006-10-01 10:28:55 +04:00
/*
* fill in basic accounting fields
*/
2012-02-08 05:56:49 +04:00
void bacct_add_tsk ( struct user_namespace * user_ns ,
struct pid_namespace * pid_ns ,
struct taskstats * stats , struct task_struct * tsk )
2006-10-01 10:28:55 +04:00
{
2008-11-14 02:39:19 +03:00
const struct cred * tcred ;
2012-11-13 17:20:55 +04:00
cputime_t utime , stime , utimescaled , stimescaled ;
2014-07-17 01:04:34 +04:00
u64 delta ;
2006-10-01 10:28:55 +04:00
BUILD_BUG_ON ( TS_COMM_LEN < TASK_COMM_LEN ) ;
2014-07-17 01:04:34 +04:00
/* calculate task elapsed time in nsec */
delta = ktime_get_ns ( ) - tsk - > start_time ;
/* Convert to micro seconds */
do_div ( delta , NSEC_PER_USEC ) ;
stats - > ac_etime = delta ;
/* Convert to seconds for btime */
do_div ( delta , USEC_PER_SEC ) ;
stats - > ac_btime = get_seconds ( ) - delta ;
2006-10-01 10:28:55 +04:00
if ( thread_group_leader ( tsk ) ) {
stats - > ac_exitcode = tsk - > exit_code ;
if ( tsk - > flags & PF_FORKNOEXEC )
stats - > ac_flag | = AFORK ;
}
if ( tsk - > flags & PF_SUPERPRIV )
stats - > ac_flag | = ASU ;
if ( tsk - > flags & PF_DUMPCORE )
stats - > ac_flag | = ACORE ;
if ( tsk - > flags & PF_SIGNALED )
stats - > ac_flag | = AXSIG ;
stats - > ac_nice = task_nice ( tsk ) ;
stats - > ac_sched = tsk - > policy ;
2012-02-08 05:56:49 +04:00
stats - > ac_pid = task_pid_nr_ns ( tsk , pid_ns ) ;
2006-10-28 21:38:50 +04:00
rcu_read_lock ( ) ;
2008-11-14 02:39:19 +03:00
tcred = __task_cred ( tsk ) ;
2012-02-08 05:56:49 +04:00
stats - > ac_uid = from_kuid_munged ( user_ns , tcred - > uid ) ;
stats - > ac_gid = from_kgid_munged ( user_ns , tcred - > gid ) ;
2006-10-28 21:38:50 +04:00
stats - > ac_ppid = pid_alive ( tsk ) ?
2012-02-08 05:56:49 +04:00
task_tgid_nr_ns ( rcu_dereference ( tsk - > real_parent ) , pid_ns ) : 0 ;
2006-10-28 21:38:50 +04:00
rcu_read_unlock ( ) ;
2012-11-13 17:20:55 +04:00
task_cputime ( tsk , & utime , & stime ) ;
stats - > ac_utime = cputime_to_usecs ( utime ) ;
stats - > ac_stime = cputime_to_usecs ( stime ) ;
task_cputime_scaled ( tsk , & utimescaled , & stimescaled ) ;
stats - > ac_utimescaled = cputime_to_usecs ( utimescaled ) ;
stats - > ac_stimescaled = cputime_to_usecs ( stimescaled ) ;
2006-10-01 10:28:55 +04:00
stats - > ac_minflt = tsk - > min_flt ;
stats - > ac_majflt = tsk - > maj_flt ;
strncpy ( stats - > ac_comm , tsk - > comm , sizeof ( stats - > ac_comm ) ) ;
}
2006-10-01 10:28:58 +04:00
# ifdef CONFIG_TASK_XACCT
2006-10-01 10:29:00 +04:00
# define KB 1024
# define MB (1024*KB)
2011-09-20 04:10:57 +04:00
# define KB_MASK (~(KB-1))
2006-10-01 10:28:58 +04:00
/*
* fill in extended accounting fields
*/
void xacct_add_tsk ( struct taskstats * stats , struct task_struct * p )
{
2006-10-30 09:46:43 +03:00
struct mm_struct * mm ;
2016-02-11 04:08:24 +03:00
/* convert pages-nsec/1024 to Mbyte-usec, see __acct_update_integrals */
stats - > coremem = p - > acct_rss_mem1 * PAGE_SIZE ;
do_div ( stats - > coremem , 1000 * KB ) ;
stats - > virtmem = p - > acct_vm_mem1 * PAGE_SIZE ;
do_div ( stats - > virtmem , 1000 * KB ) ;
2006-10-30 09:46:43 +03:00
mm = get_task_mm ( p ) ;
if ( mm ) {
2006-10-01 10:29:00 +04:00
/* adjust to KB unit */
2009-01-07 01:40:29 +03:00
stats - > hiwater_rss = get_mm_hiwater_rss ( mm ) * PAGE_SIZE / KB ;
stats - > hiwater_vm = get_mm_hiwater_vm ( mm ) * PAGE_SIZE / KB ;
2006-10-30 09:46:43 +03:00
mmput ( mm ) ;
2006-10-01 10:28:58 +04:00
}
2011-09-20 04:10:57 +04:00
stats - > read_char = p - > ioac . rchar & KB_MASK ;
stats - > write_char = p - > ioac . wchar & KB_MASK ;
stats - > read_syscalls = p - > ioac . syscr & KB_MASK ;
stats - > write_syscalls = p - > ioac . syscw & KB_MASK ;
2006-12-10 13:19:53 +03:00
# ifdef CONFIG_TASK_IO_ACCOUNTING
2011-09-20 04:10:57 +04:00
stats - > read_bytes = p - > ioac . read_bytes & KB_MASK ;
stats - > write_bytes = p - > ioac . write_bytes & KB_MASK ;
stats - > cancelled_write_bytes = p - > ioac . cancelled_write_bytes & KB_MASK ;
2006-12-10 13:19:53 +03:00
# else
stats - > read_bytes = 0 ;
stats - > write_bytes = 0 ;
stats - > cancelled_write_bytes = 0 ;
# endif
2006-10-01 10:28:58 +04:00
}
2006-10-01 10:29:00 +04:00
# undef KB
# undef MB
2006-10-01 10:28:59 +04:00
2012-11-13 17:20:55 +04:00
static void __acct_update_integrals ( struct task_struct * tsk ,
cputime_t utime , cputime_t stime )
2006-10-01 10:28:59 +04:00
{
2016-02-11 04:08:25 +03:00
cputime_t time , dtime ;
u64 delta ;
if ( ! likely ( tsk - > mm ) )
return ;
time = stime + utime ;
dtime = time - tsk - > acct_timexpd ;
/* Avoid division: cputime_t is often in nanoseconds already. */
delta = cputime_to_nsecs ( dtime ) ;
if ( delta < TICK_NSEC )
2016-02-11 04:08:26 +03:00
return ;
2016-02-11 04:08:25 +03:00
tsk - > acct_timexpd = time ;
/*
* Divide by 1024 to avoid overflow , and to avoid division .
* The final unit reported to userspace is Mbyte - usecs ,
* the rest of the math is done in xacct_add_tsk .
*/
tsk - > acct_rss_mem1 + = delta * get_mm_rss ( tsk - > mm ) > > 10 ;
tsk - > acct_vm_mem1 + = delta * tsk - > mm - > total_vm > > 10 ;
2006-10-01 10:28:59 +04:00
}
2012-11-13 17:20:55 +04:00
/**
* acct_update_integrals - update mm integral fields in task_struct
* @ tsk : task_struct for accounting
*/
void acct_update_integrals ( struct task_struct * tsk )
{
cputime_t utime , stime ;
2016-02-11 04:08:26 +03:00
unsigned long flags ;
2012-11-13 17:20:55 +04:00
2016-02-11 04:08:26 +03:00
local_irq_save ( flags ) ;
2012-11-13 17:20:55 +04:00
task_cputime ( tsk , & utime , & stime ) ;
__acct_update_integrals ( tsk , utime , stime ) ;
2016-02-11 04:08:26 +03:00
local_irq_restore ( flags ) ;
2012-11-13 17:20:55 +04:00
}
/**
* acct_account_cputime - update mm integral after cputime update
* @ tsk : task_struct for accounting
*/
void acct_account_cputime ( struct task_struct * tsk )
{
__acct_update_integrals ( tsk , tsk - > utime , tsk - > stime ) ;
}
2006-10-01 10:28:59 +04:00
/**
* acct_clear_integrals - clear the mm integral fields in task_struct
* @ tsk : task_struct whose accounting fields are cleared
*/
void acct_clear_integrals ( struct task_struct * tsk )
{
2008-07-25 12:48:40 +04:00
tsk - > acct_timexpd = 0 ;
2006-10-01 10:28:59 +04:00
tsk - > acct_rss_mem1 = 0 ;
tsk - > acct_vm_mem1 = 0 ;
}
2006-10-01 10:28:58 +04:00
# endif