📄 appldata_base.c
字号:
__appldata_vtimer_setup(APPLDATA_MOD_TIMER); spin_unlock(&appldata_timer_lock); P_INFO("Monitoring CPU interval set to %u milliseconds.\n", interval);out: *lenp = len; *ppos += len; return 0;}/* * appldata_generic_handler() * * Generic start/stop monitoring and DIAG, show status of * monitoring (0 = not in process, 1 = in process) */static intappldata_generic_handler(ctl_table *ctl, int write, struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos){ struct appldata_ops *ops = NULL, *tmp_ops; int rc, len, found; char buf[2]; struct list_head *lh; found = 0; spin_lock(&appldata_ops_lock); list_for_each(lh, &appldata_ops_list) { tmp_ops = list_entry(lh, struct appldata_ops, list); if (&tmp_ops->ctl_table[2] == ctl) { found = 1; } } if (!found) { spin_unlock(&appldata_ops_lock); return -ENODEV; } ops = ctl->data; if (!try_module_get(ops->owner)) { // protect this function spin_unlock(&appldata_ops_lock); return -ENODEV; } spin_unlock(&appldata_ops_lock); if (!*lenp || *ppos) { *lenp = 0; module_put(ops->owner); return 0; } if (!write) { len = sprintf(buf, ops->active ? "1\n" : "0\n"); if (len > *lenp) len = *lenp; if (copy_to_user(buffer, buf, len)) { module_put(ops->owner); return -EFAULT; } goto out; } len = *lenp; if (copy_from_user(buf, buffer, len > sizeof(buf) ? sizeof(buf) : len)) { module_put(ops->owner); return -EFAULT; } spin_lock(&appldata_ops_lock); if ((buf[0] == '1') && (ops->active == 0)) { // protect work queue callback if (!try_module_get(ops->owner)) { spin_unlock(&appldata_ops_lock); module_put(ops->owner); return -ENODEV; } ops->active = 1; ops->callback(ops->data); // init record rc = appldata_diag(ops->record_nr, APPLDATA_START_INTERVAL_REC, (unsigned long) ops->data, ops->size); if (rc != 0) { P_ERROR("START DIAG 0xDC for %s failed, " "return code: %d\n", ops->name, rc); module_put(ops->owner); ops->active = 0; } else { P_INFO("Monitoring %s data enabled, " "DIAG 0xDC started.\n", ops->name); } } else if ((buf[0] == '0') && (ops->active == 1)) { ops->active = 0; rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC, (unsigned long) ops->data, ops->size); if (rc != 0) { P_ERROR("STOP DIAG 0xDC for %s failed, " "return code: %d\n", ops->name, rc); } else { P_INFO("Monitoring %s data disabled, " "DIAG 0xDC stopped.\n", ops->name); } module_put(ops->owner); } spin_unlock(&appldata_ops_lock);out: *lenp = len; *ppos += len; module_put(ops->owner); return 0;}/*************************** /proc stuff <END> *******************************//************************* module-ops management *****************************//* * appldata_register_ops() * * update ops list, register /proc/sys entries */int appldata_register_ops(struct appldata_ops *ops){ struct list_head *lh; struct appldata_ops *tmp_ops; int i; i = 0; if ((ops->size > APPLDATA_MAX_REC_SIZE) || (ops->size < 0)){ P_ERROR("Invalid size of %s record = %i, maximum = %i!\n", ops->name, ops->size, APPLDATA_MAX_REC_SIZE); return -ENOMEM; } if ((ops->ctl_nr == CTL_APPLDATA) || (ops->ctl_nr == CTL_APPLDATA_TIMER) || (ops->ctl_nr == CTL_APPLDATA_INTERVAL)) { P_ERROR("ctl_nr %i already in use!\n", ops->ctl_nr); return -EBUSY; } ops->ctl_table = kmalloc(4*sizeof(struct ctl_table), GFP_KERNEL); if (ops->ctl_table == NULL) { P_ERROR("Not enough memory for %s ctl_table!\n", ops->name); return -ENOMEM; } memset(ops->ctl_table, 0, 4*sizeof(struct ctl_table)); spin_lock(&appldata_ops_lock); list_for_each(lh, &appldata_ops_list) { tmp_ops = list_entry(lh, struct appldata_ops, list); P_DEBUG("register_ops loop: %i) name = %s, ctl = %i\n", ++i, tmp_ops->name, tmp_ops->ctl_nr); P_DEBUG("Comparing %s (ctl %i) with %s (ctl %i)\n", tmp_ops->name, tmp_ops->ctl_nr, ops->name, ops->ctl_nr); if (strncmp(tmp_ops->name, ops->name, APPLDATA_PROC_NAME_LENGTH) == 0) { P_ERROR("Name \"%s\" already registered!\n", ops->name); kfree(ops->ctl_table); spin_unlock(&appldata_ops_lock); return -EBUSY; } if (tmp_ops->ctl_nr == ops->ctl_nr) { P_ERROR("ctl_nr %i already registered!\n", ops->ctl_nr); kfree(ops->ctl_table); spin_unlock(&appldata_ops_lock); return -EBUSY; } } list_add(&ops->list, &appldata_ops_list); spin_unlock(&appldata_ops_lock); ops->ctl_table[0].ctl_name = CTL_APPLDATA; ops->ctl_table[0].procname = appldata_proc_name; ops->ctl_table[0].maxlen = 0; ops->ctl_table[0].mode = S_IRUGO | S_IXUGO; ops->ctl_table[0].child = &ops->ctl_table[2]; ops->ctl_table[1].ctl_name = 0; ops->ctl_table[2].ctl_name = ops->ctl_nr; ops->ctl_table[2].procname = ops->name; ops->ctl_table[2].mode = S_IRUGO | S_IWUSR; ops->ctl_table[2].proc_handler = appldata_generic_handler; ops->ctl_table[2].data = ops; ops->ctl_table[3].ctl_name = 0; ops->sysctl_header = register_sysctl_table(ops->ctl_table,1); P_INFO("%s-ops registered!\n", ops->name); return 0;}/* * appldata_unregister_ops() * * update ops list, unregister /proc entries, stop DIAG if necessary */void appldata_unregister_ops(struct appldata_ops *ops){ void *table; spin_lock(&appldata_ops_lock); list_del(&ops->list); /* at that point any incoming access will fail */ table = ops->ctl_table; ops->ctl_table = NULL; spin_unlock(&appldata_ops_lock); unregister_sysctl_table(ops->sysctl_header); kfree(table); P_INFO("%s-ops unregistered!\n", ops->name);}/********************** module-ops management <END> **************************//******************************* init / exit *********************************/static voidappldata_online_cpu(int cpu){ init_virt_timer(&per_cpu(appldata_timer, cpu)); per_cpu(appldata_timer, cpu).function = appldata_timer_function; per_cpu(appldata_timer, cpu).data = (unsigned long) &appldata_work; atomic_inc(&appldata_expire_count); spin_lock(&appldata_timer_lock); __appldata_vtimer_setup(APPLDATA_MOD_TIMER); spin_unlock(&appldata_timer_lock);}static voidappldata_offline_cpu(int cpu){ del_virt_timer(&per_cpu(appldata_timer, cpu)); if (atomic_dec_and_test(&appldata_expire_count)) { atomic_set(&appldata_expire_count, num_online_cpus()); queue_work(appldata_wq, &appldata_work); } spin_lock(&appldata_timer_lock); __appldata_vtimer_setup(APPLDATA_MOD_TIMER); spin_unlock(&appldata_timer_lock);}static intappldata_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu){ switch (action) { case CPU_ONLINE: appldata_online_cpu((long) hcpu); break;#ifdef CONFIG_HOTPLUG_CPU case CPU_DEAD: appldata_offline_cpu((long) hcpu); break;#endif default: break; } return NOTIFY_OK;}static struct notifier_block __devinitdata appldata_nb = { .notifier_call = appldata_cpu_notify,};/* * appldata_init() * * init timer, register /proc entries */static int __init appldata_init(void){ int i; P_DEBUG("sizeof(parameter_list) = %lu\n", sizeof(struct appldata_parameter_list)); appldata_wq = create_singlethread_workqueue("appldata"); if (!appldata_wq) { P_ERROR("Could not create work queue\n"); return -ENOMEM; } for_each_online_cpu(i) appldata_online_cpu(i); /* Register cpu hotplug notifier */ register_cpu_notifier(&appldata_nb); appldata_sysctl_header = register_sysctl_table(appldata_dir_table, 1);#ifdef MODULE appldata_dir_table[0].de->owner = THIS_MODULE; appldata_table[0].de->owner = THIS_MODULE; appldata_table[1].de->owner = THIS_MODULE;#endif P_DEBUG("Base interface initialized.\n"); return 0;}/* * appldata_exit() * * stop timer, unregister /proc entries */static void __exit appldata_exit(void){ struct list_head *lh; struct appldata_ops *ops; int rc, i; P_DEBUG("Unloading module ...\n"); /* * ops list should be empty, but just in case something went wrong... */ spin_lock(&appldata_ops_lock); list_for_each(lh, &appldata_ops_list) { ops = list_entry(lh, struct appldata_ops, list); rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC, (unsigned long) ops->data, ops->size); if (rc != 0) { P_ERROR("STOP DIAG 0xDC for %s failed, " "return code: %d\n", ops->name, rc); } } spin_unlock(&appldata_ops_lock); for_each_online_cpu(i) appldata_offline_cpu(i); appldata_timer_active = 0; unregister_sysctl_table(appldata_sysctl_header); destroy_workqueue(appldata_wq); P_DEBUG("... module unloaded!\n");}/**************************** init / exit <END> ******************************/module_init(appldata_init);module_exit(appldata_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("Gerald Schaefer");MODULE_DESCRIPTION("Linux-VM Monitor Stream, base infrastructure");EXPORT_SYMBOL_GPL(appldata_register_ops);EXPORT_SYMBOL_GPL(appldata_unregister_ops);#ifdef MODULE/* * Kernel symbols needed by appldata_mem and appldata_os modules. * However, if this file is compiled as a module (for testing only), these * symbols are not exported. In this case, we define them locally and export * those. */void si_swapinfo(struct sysinfo *val){ val->freeswap = -1ul; val->totalswap = -1ul;}unsigned long avenrun[3] = {-1 - FIXED_1/200, -1 - FIXED_1/200, -1 - FIXED_1/200};int nr_threads = -1;void get_full_page_state(struct page_state *ps){ memset(ps, -1, sizeof(struct page_state));}unsigned long nr_running(void){ return -1;}unsigned long nr_iowait(void){ return -1;}/*unsigned long nr_context_switches(void){ return -1;}*/#endif /* MODULE */EXPORT_SYMBOL_GPL(si_swapinfo);EXPORT_SYMBOL_GPL(nr_threads);EXPORT_SYMBOL_GPL(avenrun);EXPORT_SYMBOL_GPL(get_full_page_state);EXPORT_SYMBOL_GPL(nr_running);EXPORT_SYMBOL_GPL(nr_iowait);//EXPORT_SYMBOL_GPL(nr_context_switches);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -