Back to home page

LXR

 
 

    


0001 /*
0002  * tsacct.c - System accounting over taskstats interface
0003  *
0004  * Copyright (C) Jay Lan,   <jlan@sgi.com>
0005  *
0006  *
0007  * This program is free software; you can redistribute it and/or modify
0008  * it under the terms of the GNU General Public License as published by
0009  * the Free Software Foundation; either version 2 of the License, or
0010  * (at your option) any later version.
0011  *
0012  * This program is distributed in the hope that it will be useful,
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0015  * GNU General Public License for more details.
0016  *
0017  */
0018 
0019 #include <linux/kernel.h>
0020 #include <linux/sched.h>
0021 #include <linux/tsacct_kern.h>
0022 #include <linux/acct.h>
0023 #include <linux/jiffies.h>
0024 #include <linux/mm.h>
0025 
0026 /*
0027  * fill in basic accounting fields
0028  */
0029 void bacct_add_tsk(struct user_namespace *user_ns,
0030            struct pid_namespace *pid_ns,
0031            struct taskstats *stats, struct task_struct *tsk)
0032 {
0033     const struct cred *tcred;
0034     cputime_t utime, stime, utimescaled, stimescaled;
0035     u64 delta;
0036 
0037     BUILD_BUG_ON(TS_COMM_LEN < TASK_COMM_LEN);
0038 
0039     /* calculate task elapsed time in nsec */
0040     delta = ktime_get_ns() - tsk->start_time;
0041     /* Convert to micro seconds */
0042     do_div(delta, NSEC_PER_USEC);
0043     stats->ac_etime = delta;
0044     /* Convert to seconds for btime */
0045     do_div(delta, USEC_PER_SEC);
0046     stats->ac_btime = get_seconds() - delta;
0047     if (thread_group_leader(tsk)) {
0048         stats->ac_exitcode = tsk->exit_code;
0049         if (tsk->flags & PF_FORKNOEXEC)
0050             stats->ac_flag |= AFORK;
0051     }
0052     if (tsk->flags & PF_SUPERPRIV)
0053         stats->ac_flag |= ASU;
0054     if (tsk->flags & PF_DUMPCORE)
0055         stats->ac_flag |= ACORE;
0056     if (tsk->flags & PF_SIGNALED)
0057         stats->ac_flag |= AXSIG;
0058     stats->ac_nice   = task_nice(tsk);
0059     stats->ac_sched  = tsk->policy;
0060     stats->ac_pid    = task_pid_nr_ns(tsk, pid_ns);
0061     rcu_read_lock();
0062     tcred = __task_cred(tsk);
0063     stats->ac_uid    = from_kuid_munged(user_ns, tcred->uid);
0064     stats->ac_gid    = from_kgid_munged(user_ns, tcred->gid);
0065     stats->ac_ppid   = pid_alive(tsk) ?
0066         task_tgid_nr_ns(rcu_dereference(tsk->real_parent), pid_ns) : 0;
0067     rcu_read_unlock();
0068 
0069     task_cputime(tsk, &utime, &stime);
0070     stats->ac_utime = cputime_to_usecs(utime);
0071     stats->ac_stime = cputime_to_usecs(stime);
0072 
0073     task_cputime_scaled(tsk, &utimescaled, &stimescaled);
0074     stats->ac_utimescaled = cputime_to_usecs(utimescaled);
0075     stats->ac_stimescaled = cputime_to_usecs(stimescaled);
0076 
0077     stats->ac_minflt = tsk->min_flt;
0078     stats->ac_majflt = tsk->maj_flt;
0079 
0080     strncpy(stats->ac_comm, tsk->comm, sizeof(stats->ac_comm));
0081 }
0082 
0083 
0084 #ifdef CONFIG_TASK_XACCT
0085 
0086 #define KB 1024
0087 #define MB (1024*KB)
0088 #define KB_MASK (~(KB-1))
0089 /*
0090  * fill in extended accounting fields
0091  */
0092 void xacct_add_tsk(struct taskstats *stats, struct task_struct *p)
0093 {
0094     struct mm_struct *mm;
0095 
0096     /* convert pages-nsec/1024 to Mbyte-usec, see __acct_update_integrals */
0097     stats->coremem = p->acct_rss_mem1 * PAGE_SIZE;
0098     do_div(stats->coremem, 1000 * KB);
0099     stats->virtmem = p->acct_vm_mem1 * PAGE_SIZE;
0100     do_div(stats->virtmem, 1000 * KB);
0101     mm = get_task_mm(p);
0102     if (mm) {
0103         /* adjust to KB unit */
0104         stats->hiwater_rss   = get_mm_hiwater_rss(mm) * PAGE_SIZE / KB;
0105         stats->hiwater_vm    = get_mm_hiwater_vm(mm)  * PAGE_SIZE / KB;
0106         mmput(mm);
0107     }
0108     stats->read_char    = p->ioac.rchar & KB_MASK;
0109     stats->write_char   = p->ioac.wchar & KB_MASK;
0110     stats->read_syscalls    = p->ioac.syscr & KB_MASK;
0111     stats->write_syscalls   = p->ioac.syscw & KB_MASK;
0112 #ifdef CONFIG_TASK_IO_ACCOUNTING
0113     stats->read_bytes   = p->ioac.read_bytes & KB_MASK;
0114     stats->write_bytes  = p->ioac.write_bytes & KB_MASK;
0115     stats->cancelled_write_bytes = p->ioac.cancelled_write_bytes & KB_MASK;
0116 #else
0117     stats->read_bytes   = 0;
0118     stats->write_bytes  = 0;
0119     stats->cancelled_write_bytes = 0;
0120 #endif
0121 }
0122 #undef KB
0123 #undef MB
0124 
0125 static void __acct_update_integrals(struct task_struct *tsk,
0126                     cputime_t utime, cputime_t stime)
0127 {
0128     cputime_t time, dtime;
0129     u64 delta;
0130 
0131     if (!likely(tsk->mm))
0132         return;
0133 
0134     time = stime + utime;
0135     dtime = time - tsk->acct_timexpd;
0136     /* Avoid division: cputime_t is often in nanoseconds already. */
0137     delta = cputime_to_nsecs(dtime);
0138 
0139     if (delta < TICK_NSEC)
0140         return;
0141 
0142     tsk->acct_timexpd = time;
0143     /*
0144      * Divide by 1024 to avoid overflow, and to avoid division.
0145      * The final unit reported to userspace is Mbyte-usecs,
0146      * the rest of the math is done in xacct_add_tsk.
0147      */
0148     tsk->acct_rss_mem1 += delta * get_mm_rss(tsk->mm) >> 10;
0149     tsk->acct_vm_mem1 += delta * tsk->mm->total_vm >> 10;
0150 }
0151 
0152 /**
0153  * acct_update_integrals - update mm integral fields in task_struct
0154  * @tsk: task_struct for accounting
0155  */
0156 void acct_update_integrals(struct task_struct *tsk)
0157 {
0158     cputime_t utime, stime;
0159     unsigned long flags;
0160 
0161     local_irq_save(flags);
0162     task_cputime(tsk, &utime, &stime);
0163     __acct_update_integrals(tsk, utime, stime);
0164     local_irq_restore(flags);
0165 }
0166 
0167 /**
0168  * acct_account_cputime - update mm integral after cputime update
0169  * @tsk: task_struct for accounting
0170  */
0171 void acct_account_cputime(struct task_struct *tsk)
0172 {
0173     __acct_update_integrals(tsk, tsk->utime, tsk->stime);
0174 }
0175 
0176 /**
0177  * acct_clear_integrals - clear the mm integral fields in task_struct
0178  * @tsk: task_struct whose accounting fields are cleared
0179  */
0180 void acct_clear_integrals(struct task_struct *tsk)
0181 {
0182     tsk->acct_timexpd = 0;
0183     tsk->acct_rss_mem1 = 0;
0184     tsk->acct_vm_mem1 = 0;
0185 }
0186 #endif