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 ;
2006-10-01 10:28:55 +04:00
struct timespec uptime , ts ;
2012-11-13 17:20:55 +04:00
cputime_t utime , stime , utimescaled , stimescaled ;
2008-07-25 12:48:50 +04:00
u64 ac_etime ;
2006-10-01 10:28:55 +04:00
BUILD_BUG_ON ( TS_COMM_LEN < TASK_COMM_LEN ) ;
/* calculate task elapsed time in timespec */
do_posix_clock_monotonic_gettime ( & uptime ) ;
2006-10-28 21:38:50 +04:00
ts = timespec_sub ( uptime , tsk - > start_time ) ;
2008-07-25 12:48:50 +04:00
/* rebase elapsed time to usec (should never be negative) */
2006-10-01 10:28:55 +04:00
ac_etime = timespec_to_ns ( & ts ) ;
do_div ( ac_etime , NSEC_PER_USEC ) ;
stats - > ac_etime = ac_etime ;
2007-07-25 04:47:43 +04:00
stats - > ac_btime = get_seconds ( ) - ts . tv_sec ;
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 ;
2008-07-25 12:48:40 +04:00
/* convert pages-usec to Mbyte-usec */
stats - > coremem = p - > acct_rss_mem1 * PAGE_SIZE / MB ;
stats - > virtmem = p - > acct_vm_mem1 * PAGE_SIZE / MB ;
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
{
if ( likely ( tsk - > mm ) ) {
2008-07-25 12:48:40 +04:00
cputime_t time , dtime ;
struct timeval value ;
Fix fixpoint divide exception in acct_update_integrals
Frans Pop reported the crash below when running an s390 kernel under Hercules:
Kernel BUG at 000738b4 verbose debug info unavailable!
fixpoint divide exception: 0009 #1! SMP
Modules linked in: nfs lockd nfs_acl sunrpc ctcm fsm tape_34xx
cu3088 tape ccwgroup tape_class ext3 jbd mbcache dm_mirror dm_log dm_snapshot
dm_mod dasd_eckd_mod dasd_mod
CPU: 0 Not tainted 2.6.27.19 #13
Process awk (pid: 2069, task: 0f9ed9b8, ksp: 0f4f7d18)
Krnl PSW : 070c1000 800738b4 (acct_update_integrals+0x4c/0x118)
R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:0 CC:1 PM:0
Krnl GPRS: 00000000 000007d0 7fffffff fffff830
00000000 ffffffff 00000002 0f9ed9b8
00000000 00008ca0 00000000 0f9ed9b8
0f9edda4 8007386e 0f4f7ec8 0f4f7e98
Krnl Code: 800738aa: a71807d0 lhi %r1,2000
800738ae: 8c200001 srdl %r2,1
800738b2: 1d21 dr %r2,%r1
>800738b4: 5810d10e l %r1,270(%r13)
800738b8: 1823 lr %r2,%r3
800738ba: 4130f060 la %r3,96(%r15)
800738be: 0de1 basr %r14,%r1
800738c0: 5800f060 l %r0,96(%r15)
Call Trace:
( <000000000004fdea>! blocking_notifier_call_chain+0x1e/0x2c)
<0000000000038502>! do_exit+0x106/0x7c0
<0000000000038c36>! do_group_exit+0x7a/0xb4
<0000000000038c8e>! SyS_exit_group+0x1e/0x30
<0000000000021c28>! sysc_do_restart+0x12/0x16
<0000000077e7e924>! 0x77e7e924
Reason for this is that cpu time accounting usually only happens from
interrupt context, but acct_update_integrals gets also called from
process context with interrupts enabled.
So in acct_update_integrals we may end up with the following scenario:
Between reading tsk->stime/tsk->utime and tsk->acct_timexpd an interrupt
happens which updates accouting values. This causes acct_timexpd to be
greater than the former stime + utime. The subsequent calculation of
dtime = cputime_sub(time, tsk->acct_timexpd);
will be negative and the division performed by
cputime_to_jiffies(dtime)
will generate an exception since the result won't fit into a 32 bit
register.
In order to fix this just always disable interrupts while accessing any
of the accounting values.
Reported by: Frans Pop <elendil@planet.nl>
Tested by: Frans Pop <elendil@planet.nl>
Cc: stable@kernel.org
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-03-09 15:31:59 +03:00
unsigned long flags ;
2008-07-25 12:48:40 +04:00
u64 delta ;
Fix fixpoint divide exception in acct_update_integrals
Frans Pop reported the crash below when running an s390 kernel under Hercules:
Kernel BUG at 000738b4 verbose debug info unavailable!
fixpoint divide exception: 0009 #1! SMP
Modules linked in: nfs lockd nfs_acl sunrpc ctcm fsm tape_34xx
cu3088 tape ccwgroup tape_class ext3 jbd mbcache dm_mirror dm_log dm_snapshot
dm_mod dasd_eckd_mod dasd_mod
CPU: 0 Not tainted 2.6.27.19 #13
Process awk (pid: 2069, task: 0f9ed9b8, ksp: 0f4f7d18)
Krnl PSW : 070c1000 800738b4 (acct_update_integrals+0x4c/0x118)
R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:0 CC:1 PM:0
Krnl GPRS: 00000000 000007d0 7fffffff fffff830
00000000 ffffffff 00000002 0f9ed9b8
00000000 00008ca0 00000000 0f9ed9b8
0f9edda4 8007386e 0f4f7ec8 0f4f7e98
Krnl Code: 800738aa: a71807d0 lhi %r1,2000
800738ae: 8c200001 srdl %r2,1
800738b2: 1d21 dr %r2,%r1
>800738b4: 5810d10e l %r1,270(%r13)
800738b8: 1823 lr %r2,%r3
800738ba: 4130f060 la %r3,96(%r15)
800738be: 0de1 basr %r14,%r1
800738c0: 5800f060 l %r0,96(%r15)
Call Trace:
( <000000000004fdea>! blocking_notifier_call_chain+0x1e/0x2c)
<0000000000038502>! do_exit+0x106/0x7c0
<0000000000038c36>! do_group_exit+0x7a/0xb4
<0000000000038c8e>! SyS_exit_group+0x1e/0x30
<0000000000021c28>! sysc_do_restart+0x12/0x16
<0000000077e7e924>! 0x77e7e924
Reason for this is that cpu time accounting usually only happens from
interrupt context, but acct_update_integrals gets also called from
process context with interrupts enabled.
So in acct_update_integrals we may end up with the following scenario:
Between reading tsk->stime/tsk->utime and tsk->acct_timexpd an interrupt
happens which updates accouting values. This causes acct_timexpd to be
greater than the former stime + utime. The subsequent calculation of
dtime = cputime_sub(time, tsk->acct_timexpd);
will be negative and the division performed by
cputime_to_jiffies(dtime)
will generate an exception since the result won't fit into a 32 bit
register.
In order to fix this just always disable interrupts while accessing any
of the accounting values.
Reported by: Frans Pop <elendil@planet.nl>
Tested by: Frans Pop <elendil@planet.nl>
Cc: stable@kernel.org
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-03-09 15:31:59 +03:00
local_irq_save ( flags ) ;
2012-11-13 17:20:55 +04:00
time = stime + utime ;
2011-12-15 17:56:09 +04:00
dtime = time - tsk - > acct_timexpd ;
2008-07-25 12:48:40 +04:00
jiffies_to_timeval ( cputime_to_jiffies ( dtime ) , & value ) ;
delta = value . tv_sec ;
delta = delta * USEC_PER_SEC + value . tv_usec ;
2006-10-01 10:28:59 +04:00
if ( delta = = 0 )
Fix fixpoint divide exception in acct_update_integrals
Frans Pop reported the crash below when running an s390 kernel under Hercules:
Kernel BUG at 000738b4 verbose debug info unavailable!
fixpoint divide exception: 0009 #1! SMP
Modules linked in: nfs lockd nfs_acl sunrpc ctcm fsm tape_34xx
cu3088 tape ccwgroup tape_class ext3 jbd mbcache dm_mirror dm_log dm_snapshot
dm_mod dasd_eckd_mod dasd_mod
CPU: 0 Not tainted 2.6.27.19 #13
Process awk (pid: 2069, task: 0f9ed9b8, ksp: 0f4f7d18)
Krnl PSW : 070c1000 800738b4 (acct_update_integrals+0x4c/0x118)
R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:0 CC:1 PM:0
Krnl GPRS: 00000000 000007d0 7fffffff fffff830
00000000 ffffffff 00000002 0f9ed9b8
00000000 00008ca0 00000000 0f9ed9b8
0f9edda4 8007386e 0f4f7ec8 0f4f7e98
Krnl Code: 800738aa: a71807d0 lhi %r1,2000
800738ae: 8c200001 srdl %r2,1
800738b2: 1d21 dr %r2,%r1
>800738b4: 5810d10e l %r1,270(%r13)
800738b8: 1823 lr %r2,%r3
800738ba: 4130f060 la %r3,96(%r15)
800738be: 0de1 basr %r14,%r1
800738c0: 5800f060 l %r0,96(%r15)
Call Trace:
( <000000000004fdea>! blocking_notifier_call_chain+0x1e/0x2c)
<0000000000038502>! do_exit+0x106/0x7c0
<0000000000038c36>! do_group_exit+0x7a/0xb4
<0000000000038c8e>! SyS_exit_group+0x1e/0x30
<0000000000021c28>! sysc_do_restart+0x12/0x16
<0000000077e7e924>! 0x77e7e924
Reason for this is that cpu time accounting usually only happens from
interrupt context, but acct_update_integrals gets also called from
process context with interrupts enabled.
So in acct_update_integrals we may end up with the following scenario:
Between reading tsk->stime/tsk->utime and tsk->acct_timexpd an interrupt
happens which updates accouting values. This causes acct_timexpd to be
greater than the former stime + utime. The subsequent calculation of
dtime = cputime_sub(time, tsk->acct_timexpd);
will be negative and the division performed by
cputime_to_jiffies(dtime)
will generate an exception since the result won't fit into a 32 bit
register.
In order to fix this just always disable interrupts while accessing any
of the accounting values.
Reported by: Frans Pop <elendil@planet.nl>
Tested by: Frans Pop <elendil@planet.nl>
Cc: stable@kernel.org
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-03-09 15:31:59 +03:00
goto out ;
2008-07-25 12:48:40 +04:00
tsk - > acct_timexpd = time ;
2006-10-01 10:28:59 +04:00
tsk - > acct_rss_mem1 + = delta * get_mm_rss ( tsk - > mm ) ;
tsk - > acct_vm_mem1 + = delta * tsk - > mm - > total_vm ;
Fix fixpoint divide exception in acct_update_integrals
Frans Pop reported the crash below when running an s390 kernel under Hercules:
Kernel BUG at 000738b4 verbose debug info unavailable!
fixpoint divide exception: 0009 #1! SMP
Modules linked in: nfs lockd nfs_acl sunrpc ctcm fsm tape_34xx
cu3088 tape ccwgroup tape_class ext3 jbd mbcache dm_mirror dm_log dm_snapshot
dm_mod dasd_eckd_mod dasd_mod
CPU: 0 Not tainted 2.6.27.19 #13
Process awk (pid: 2069, task: 0f9ed9b8, ksp: 0f4f7d18)
Krnl PSW : 070c1000 800738b4 (acct_update_integrals+0x4c/0x118)
R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:0 CC:1 PM:0
Krnl GPRS: 00000000 000007d0 7fffffff fffff830
00000000 ffffffff 00000002 0f9ed9b8
00000000 00008ca0 00000000 0f9ed9b8
0f9edda4 8007386e 0f4f7ec8 0f4f7e98
Krnl Code: 800738aa: a71807d0 lhi %r1,2000
800738ae: 8c200001 srdl %r2,1
800738b2: 1d21 dr %r2,%r1
>800738b4: 5810d10e l %r1,270(%r13)
800738b8: 1823 lr %r2,%r3
800738ba: 4130f060 la %r3,96(%r15)
800738be: 0de1 basr %r14,%r1
800738c0: 5800f060 l %r0,96(%r15)
Call Trace:
( <000000000004fdea>! blocking_notifier_call_chain+0x1e/0x2c)
<0000000000038502>! do_exit+0x106/0x7c0
<0000000000038c36>! do_group_exit+0x7a/0xb4
<0000000000038c8e>! SyS_exit_group+0x1e/0x30
<0000000000021c28>! sysc_do_restart+0x12/0x16
<0000000077e7e924>! 0x77e7e924
Reason for this is that cpu time accounting usually only happens from
interrupt context, but acct_update_integrals gets also called from
process context with interrupts enabled.
So in acct_update_integrals we may end up with the following scenario:
Between reading tsk->stime/tsk->utime and tsk->acct_timexpd an interrupt
happens which updates accouting values. This causes acct_timexpd to be
greater than the former stime + utime. The subsequent calculation of
dtime = cputime_sub(time, tsk->acct_timexpd);
will be negative and the division performed by
cputime_to_jiffies(dtime)
will generate an exception since the result won't fit into a 32 bit
register.
In order to fix this just always disable interrupts while accessing any
of the accounting values.
Reported by: Frans Pop <elendil@planet.nl>
Tested by: Frans Pop <elendil@planet.nl>
Cc: stable@kernel.org
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2009-03-09 15:31:59 +03:00
out :
local_irq_restore ( flags ) ;
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 ;
task_cputime ( tsk , & utime , & stime ) ;
__acct_update_integrals ( tsk , utime , stime ) ;
}
/**
* 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