Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later 2 : : /* 3 : : * tsacct.c - System accounting over taskstats interface 4 : : * 5 : : * Copyright (C) Jay Lan, <jlan@sgi.com> 6 : : */ 7 : : 8 : : #include <linux/kernel.h> 9 : : #include <linux/sched/signal.h> 10 : : #include <linux/sched/mm.h> 11 : : #include <linux/sched/cputime.h> 12 : : #include <linux/tsacct_kern.h> 13 : : #include <linux/acct.h> 14 : : #include <linux/jiffies.h> 15 : : #include <linux/mm.h> 16 : : 17 : : /* 18 : : * fill in basic accounting fields 19 : : */ 20 : 0 : void bacct_add_tsk(struct user_namespace *user_ns, 21 : : struct pid_namespace *pid_ns, 22 : : struct taskstats *stats, struct task_struct *tsk) 23 : : { 24 : : const struct cred *tcred; 25 : : u64 utime, stime, utimescaled, stimescaled; 26 : : u64 delta; 27 : : 28 : : BUILD_BUG_ON(TS_COMM_LEN < TASK_COMM_LEN); 29 : : 30 : : /* calculate task elapsed time in nsec */ 31 : 0 : delta = ktime_get_ns() - tsk->start_time; 32 : : /* Convert to micro seconds */ 33 : 0 : do_div(delta, NSEC_PER_USEC); 34 : 0 : stats->ac_etime = delta; 35 : : /* Convert to seconds for btime */ 36 : 0 : do_div(delta, USEC_PER_SEC); 37 : 0 : stats->ac_btime = get_seconds() - delta; 38 [ # # ]: 0 : if (thread_group_leader(tsk)) { 39 : 0 : stats->ac_exitcode = tsk->exit_code; 40 [ # # ]: 0 : if (tsk->flags & PF_FORKNOEXEC) 41 : 0 : stats->ac_flag |= AFORK; 42 : : } 43 [ # # ]: 0 : if (tsk->flags & PF_SUPERPRIV) 44 : 0 : stats->ac_flag |= ASU; 45 [ # # ]: 0 : if (tsk->flags & PF_DUMPCORE) 46 : 0 : stats->ac_flag |= ACORE; 47 [ # # ]: 0 : if (tsk->flags & PF_SIGNALED) 48 : 0 : stats->ac_flag |= AXSIG; 49 : 0 : stats->ac_nice = task_nice(tsk); 50 : 0 : stats->ac_sched = tsk->policy; 51 : 0 : stats->ac_pid = task_pid_nr_ns(tsk, pid_ns); 52 : : rcu_read_lock(); 53 : 0 : tcred = __task_cred(tsk); 54 : 0 : stats->ac_uid = from_kuid_munged(user_ns, tcred->uid); 55 : 0 : stats->ac_gid = from_kgid_munged(user_ns, tcred->gid); 56 [ # # ]: 0 : stats->ac_ppid = pid_alive(tsk) ? 57 : 0 : task_tgid_nr_ns(rcu_dereference(tsk->real_parent), pid_ns) : 0; 58 : : rcu_read_unlock(); 59 : : 60 : : task_cputime(tsk, &utime, &stime); 61 : 0 : stats->ac_utime = div_u64(utime, NSEC_PER_USEC); 62 : 0 : stats->ac_stime = div_u64(stime, NSEC_PER_USEC); 63 : : 64 : : task_cputime_scaled(tsk, &utimescaled, &stimescaled); 65 : 0 : stats->ac_utimescaled = div_u64(utimescaled, NSEC_PER_USEC); 66 : 0 : stats->ac_stimescaled = div_u64(stimescaled, NSEC_PER_USEC); 67 : : 68 : 0 : stats->ac_minflt = tsk->min_flt; 69 : 0 : stats->ac_majflt = tsk->maj_flt; 70 : : 71 : 0 : strncpy(stats->ac_comm, tsk->comm, sizeof(stats->ac_comm)); 72 : 0 : } 73 : : 74 : : 75 : : #ifdef CONFIG_TASK_XACCT 76 : : 77 : : #define KB 1024 78 : : #define MB (1024*KB) 79 : : #define KB_MASK (~(KB-1)) 80 : : /* 81 : : * fill in extended accounting fields 82 : : */ 83 : 0 : void xacct_add_tsk(struct taskstats *stats, struct task_struct *p) 84 : : { 85 : : struct mm_struct *mm; 86 : : 87 : : /* convert pages-nsec/1024 to Mbyte-usec, see __acct_update_integrals */ 88 : 0 : stats->coremem = p->acct_rss_mem1 * PAGE_SIZE; 89 : 0 : do_div(stats->coremem, 1000 * KB); 90 : 0 : stats->virtmem = p->acct_vm_mem1 * PAGE_SIZE; 91 : 0 : do_div(stats->virtmem, 1000 * KB); 92 : 0 : mm = get_task_mm(p); 93 [ # # ]: 0 : if (mm) { 94 : : /* adjust to KB unit */ 95 : 0 : stats->hiwater_rss = get_mm_hiwater_rss(mm) * PAGE_SIZE / KB; 96 : 0 : stats->hiwater_vm = get_mm_hiwater_vm(mm) * PAGE_SIZE / KB; 97 : 0 : mmput(mm); 98 : : } 99 : 0 : stats->read_char = p->ioac.rchar & KB_MASK; 100 : 0 : stats->write_char = p->ioac.wchar & KB_MASK; 101 : 0 : stats->read_syscalls = p->ioac.syscr & KB_MASK; 102 : 0 : stats->write_syscalls = p->ioac.syscw & KB_MASK; 103 : : #ifdef CONFIG_TASK_IO_ACCOUNTING 104 : 0 : stats->read_bytes = p->ioac.read_bytes & KB_MASK; 105 : 0 : stats->write_bytes = p->ioac.write_bytes & KB_MASK; 106 : 0 : stats->cancelled_write_bytes = p->ioac.cancelled_write_bytes & KB_MASK; 107 : : #else 108 : : stats->read_bytes = 0; 109 : : stats->write_bytes = 0; 110 : : stats->cancelled_write_bytes = 0; 111 : : #endif 112 : 0 : } 113 : : #undef KB 114 : : #undef MB 115 : : 116 : 13832266 : static void __acct_update_integrals(struct task_struct *tsk, 117 : : u64 utime, u64 stime) 118 : : { 119 : : u64 time, delta; 120 : : 121 [ + + ]: 13832266 : if (!likely(tsk->mm)) 122 : : return; 123 : : 124 : 8955284 : time = stime + utime; 125 : 8955284 : delta = time - tsk->acct_timexpd; 126 : : 127 [ + + ]: 8955284 : if (delta < TICK_NSEC) 128 : : return; 129 : : 130 : 8167070 : tsk->acct_timexpd = time; 131 : : /* 132 : : * Divide by 1024 to avoid overflow, and to avoid division. 133 : : * The final unit reported to userspace is Mbyte-usecs, 134 : : * the rest of the math is done in xacct_add_tsk. 135 : : */ 136 : 8167070 : tsk->acct_rss_mem1 += delta * get_mm_rss(tsk->mm) >> 10; 137 : 8167070 : tsk->acct_vm_mem1 += delta * tsk->mm->total_vm >> 10; 138 : : } 139 : : 140 : : /** 141 : : * acct_update_integrals - update mm integral fields in task_struct 142 : : * @tsk: task_struct for accounting 143 : : */ 144 : 790536 : void acct_update_integrals(struct task_struct *tsk) 145 : : { 146 : : u64 utime, stime; 147 : : unsigned long flags; 148 : : 149 : 790548 : local_irq_save(flags); 150 : : task_cputime(tsk, &utime, &stime); 151 : 790540 : __acct_update_integrals(tsk, utime, stime); 152 [ - + ]: 790546 : local_irq_restore(flags); 153 : 790544 : } 154 : : 155 : : /** 156 : : * acct_account_cputime - update mm integral after cputime update 157 : : * @tsk: task_struct for accounting 158 : : */ 159 : 13040240 : void acct_account_cputime(struct task_struct *tsk) 160 : : { 161 : 13040240 : __acct_update_integrals(tsk, tsk->utime, tsk->stime); 162 : 13003396 : } 163 : : 164 : : /** 165 : : * acct_clear_integrals - clear the mm integral fields in task_struct 166 : : * @tsk: task_struct whose accounting fields are cleared 167 : : */ 168 : 490168 : void acct_clear_integrals(struct task_struct *tsk) 169 : : { 170 : 490168 : tsk->acct_timexpd = 0; 171 : 490168 : tsk->acct_rss_mem1 = 0; 172 : 490168 : tsk->acct_vm_mem1 = 0; 173 : 490168 : } 174 : : #endif