0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #define KMSG_COMPONENT "appldata"
0012 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
0013
0014 #include <linux/module.h>
0015 #include <linux/init.h>
0016 #include <linux/slab.h>
0017 #include <linux/errno.h>
0018 #include <linux/kernel_stat.h>
0019 #include <linux/netdevice.h>
0020 #include <linux/sched.h>
0021 #include <linux/sched/loadavg.h>
0022 #include <linux/sched/stat.h>
0023 #include <asm/appldata.h>
0024 #include <asm/smp.h>
0025
0026 #include "appldata.h"
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 struct appldata_os_per_cpu {
0037 u32 per_cpu_user;
0038 u32 per_cpu_nice;
0039 u32 per_cpu_system;
0040 u32 per_cpu_idle;
0041
0042
0043 u32 per_cpu_irq;
0044 u32 per_cpu_softirq;
0045 u32 per_cpu_iowait;
0046
0047
0048 u32 per_cpu_steal;
0049 u32 cpu_id;
0050 } __attribute__((packed));
0051
0052 struct appldata_os_data {
0053 u64 timestamp;
0054 u32 sync_count_1;
0055 u32 sync_count_2;
0056
0057
0058
0059
0060 u32 nr_cpus;
0061 u32 per_cpu_size;
0062 u32 cpu_offset;
0063
0064 u32 nr_running;
0065 u32 nr_threads;
0066 u32 avenrun[3];
0067
0068
0069
0070 u32 nr_iowait;
0071
0072
0073
0074 struct appldata_os_per_cpu os_cpu[];
0075 } __attribute__((packed));
0076
0077 static struct appldata_os_data *appldata_os_data;
0078
0079 static struct appldata_ops ops = {
0080 .name = "os",
0081 .record_nr = APPLDATA_RECORD_OS_ID,
0082 .owner = THIS_MODULE,
0083 .mod_lvl = {0xF0, 0xF1},
0084 };
0085
0086
0087
0088
0089
0090
0091
0092 static void appldata_get_os_data(void *data)
0093 {
0094 int i, j, rc;
0095 struct appldata_os_data *os_data;
0096 unsigned int new_size;
0097
0098 os_data = data;
0099 os_data->sync_count_1++;
0100
0101 os_data->nr_threads = nr_threads;
0102 os_data->nr_running = nr_running();
0103 os_data->nr_iowait = nr_iowait();
0104 os_data->avenrun[0] = avenrun[0] + (FIXED_1/200);
0105 os_data->avenrun[1] = avenrun[1] + (FIXED_1/200);
0106 os_data->avenrun[2] = avenrun[2] + (FIXED_1/200);
0107
0108 j = 0;
0109 for_each_online_cpu(i) {
0110 os_data->os_cpu[j].per_cpu_user =
0111 nsecs_to_jiffies(kcpustat_cpu(i).cpustat[CPUTIME_USER]);
0112 os_data->os_cpu[j].per_cpu_nice =
0113 nsecs_to_jiffies(kcpustat_cpu(i).cpustat[CPUTIME_NICE]);
0114 os_data->os_cpu[j].per_cpu_system =
0115 nsecs_to_jiffies(kcpustat_cpu(i).cpustat[CPUTIME_SYSTEM]);
0116 os_data->os_cpu[j].per_cpu_idle =
0117 nsecs_to_jiffies(kcpustat_cpu(i).cpustat[CPUTIME_IDLE]);
0118 os_data->os_cpu[j].per_cpu_irq =
0119 nsecs_to_jiffies(kcpustat_cpu(i).cpustat[CPUTIME_IRQ]);
0120 os_data->os_cpu[j].per_cpu_softirq =
0121 nsecs_to_jiffies(kcpustat_cpu(i).cpustat[CPUTIME_SOFTIRQ]);
0122 os_data->os_cpu[j].per_cpu_iowait =
0123 nsecs_to_jiffies(kcpustat_cpu(i).cpustat[CPUTIME_IOWAIT]);
0124 os_data->os_cpu[j].per_cpu_steal =
0125 nsecs_to_jiffies(kcpustat_cpu(i).cpustat[CPUTIME_STEAL]);
0126 os_data->os_cpu[j].cpu_id = i;
0127 j++;
0128 }
0129
0130 os_data->nr_cpus = j;
0131
0132 new_size = struct_size(os_data, os_cpu, os_data->nr_cpus);
0133 if (ops.size != new_size) {
0134 if (ops.active) {
0135 rc = appldata_diag(APPLDATA_RECORD_OS_ID,
0136 APPLDATA_START_INTERVAL_REC,
0137 (unsigned long) ops.data, new_size,
0138 ops.mod_lvl);
0139 if (rc != 0)
0140 pr_err("Starting a new OS data collection "
0141 "failed with rc=%d\n", rc);
0142
0143 rc = appldata_diag(APPLDATA_RECORD_OS_ID,
0144 APPLDATA_STOP_REC,
0145 (unsigned long) ops.data, ops.size,
0146 ops.mod_lvl);
0147 if (rc != 0)
0148 pr_err("Stopping a faulty OS data "
0149 "collection failed with rc=%d\n", rc);
0150 }
0151 ops.size = new_size;
0152 }
0153 os_data->timestamp = get_tod_clock();
0154 os_data->sync_count_2++;
0155 }
0156
0157
0158
0159
0160
0161
0162
0163 static int __init appldata_os_init(void)
0164 {
0165 int rc, max_size;
0166
0167 max_size = struct_size(appldata_os_data, os_cpu, num_possible_cpus());
0168 if (max_size > APPLDATA_MAX_REC_SIZE) {
0169 pr_err("Maximum OS record size %i exceeds the maximum "
0170 "record size %i\n", max_size, APPLDATA_MAX_REC_SIZE);
0171 rc = -ENOMEM;
0172 goto out;
0173 }
0174
0175 appldata_os_data = kzalloc(max_size, GFP_KERNEL | GFP_DMA);
0176 if (appldata_os_data == NULL) {
0177 rc = -ENOMEM;
0178 goto out;
0179 }
0180
0181 appldata_os_data->per_cpu_size = sizeof(struct appldata_os_per_cpu);
0182 appldata_os_data->cpu_offset = offsetof(struct appldata_os_data,
0183 os_cpu);
0184
0185 ops.data = appldata_os_data;
0186 ops.callback = &appldata_get_os_data;
0187 rc = appldata_register_ops(&ops);
0188 if (rc != 0)
0189 kfree(appldata_os_data);
0190 out:
0191 return rc;
0192 }
0193
0194
0195
0196
0197
0198
0199 static void __exit appldata_os_exit(void)
0200 {
0201 appldata_unregister_ops(&ops);
0202 kfree(appldata_os_data);
0203 }
0204
0205
0206 module_init(appldata_os_init);
0207 module_exit(appldata_os_exit);
0208
0209 MODULE_LICENSE("GPL");
0210 MODULE_AUTHOR("Gerald Schaefer");
0211 MODULE_DESCRIPTION("Linux-VM Monitor Stream, OS statistics");