[PATCH 3/3] introduce "account modifiers" mechanism in the kernel allowing a module to modify the collected accounting for a given task. This implementation is based on the "preempt_notifier". "account_system_time()" and "account_user_time()" can call functions registered by a module to modify the cputime value. Signed-off-by: Laurent Vivier <Laurent.Vivier@xxxxxxxx> -- ------------- Laurent.Vivier@xxxxxxxx -------------- "Software is hard" - Donald Knuth
Index: kvm/include/linux/sched.h =================================================================== --- kvm.orig/include/linux/sched.h 2007-08-16 15:23:27.000000000 +0200 +++ kvm/include/linux/sched.h 2007-08-16 15:23:41.000000000 +0200 @@ -955,6 +955,10 @@ /* list of struct preempt_notifier: */ struct hlist_head preempt_notifiers; #endif +#ifdef CONFIG_ACCOUNT_MODIFIERS + /* list of struct account_modifiers: */ + struct hlist_head account_modifiers; +#endif unsigned short ioprio; #ifdef CONFIG_BLK_DEV_IO_TRACE @@ -1873,6 +1877,31 @@ } #endif +#ifdef CONFIG_ACCOUNT_MODIFIERS +struct account_modifier; +struct account_ops { + cputime_t (*user_time)(struct account_modifier *, + struct task_struct *, cputime_t ); + cputime_t (*system_time)(struct account_modifier *, + struct task_struct *, int, cputime_t); +}; + +struct account_modifier { + struct hlist_node link; + struct account_ops *ops; +}; + +void account_modifier_register(struct account_modifier *modifier); +void account_modifier_unregister(struct account_modifier *modifier); + +static inline void account_modifier_init(struct account_modifier *modifier, + struct account_ops *ops) +{ + INIT_HLIST_NODE(&modifier->link); + modifier->ops = ops; +} +#endif + #endif /* __KERNEL__ */ #endif Index: kvm/kernel/sched.c =================================================================== --- kvm.orig/kernel/sched.c 2007-08-16 15:15:33.000000000 +0200 +++ kvm/kernel/sched.c 2007-08-16 15:23:28.000000000 +0200 @@ -1593,6 +1593,9 @@ #ifdef CONFIG_PREEMPT_NOTIFIERS INIT_HLIST_HEAD(&p->preempt_notifiers); #endif +#ifdef CONFIG_ACCOUNT_MODIFIERS + INIT_HLIST_HEAD(&p->account_modifiers); +#endif /* * We mark the process as running here, but have not actually @@ -1731,6 +1734,62 @@ } #endif +#ifdef CONFIG_ACCOUNT_MODIFIERS + +void account_modifier_register(struct account_modifier *modifier) +{ + hlist_add_head(&modifier->link, ¤t->account_modifiers); +} +EXPORT_SYMBOL_GPL(account_modifier_register); + +void account_modifier_unregister(struct account_modifier *modifier) +{ + hlist_del(&modifier->link); +} +EXPORT_SYMBOL_GPL(account_modifier_unregister); + +static cputime_t fire_user_time_account_modifiers(struct task_struct *curr, + cputime_t cputime) +{ + struct account_modifier *modifier; + struct hlist_node *node; + + hlist_for_each_entry(modifier, node, &curr->account_modifiers, link) + if (modifier->ops->user_time) + cputime = modifier->ops->user_time(modifier, + curr, cputime); + return cputime; +} + +static cputime_t fire_system_time_account_modifiers(struct task_struct *curr, + int hardirq_offset, + cputime_t cputime) +{ + struct account_modifier *modifier; + struct hlist_node *node; + + hlist_for_each_entry(modifier, node, &curr->account_modifiers, link) + if (modifier->ops->system_time) + cputime = modifier->ops->system_time(modifier, + curr, hardirq_offset, cputime); + return cputime; +} + +#else + +static inline cputime_t fire_user_time_account_modifiers(struct task_struct *curr, cputime_t cputime) +{ + return cputime; +} + +static inline cputime_t fire_system_time_account_modifiers(struct task_struct *curr, + int hardirq_offset, + cputime_t cputime) +{ + return cputime; +} + +#endif /** * prepare_task_switch - prepare to switch tasks @@ -3223,6 +3282,8 @@ struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; cputime64_t tmp; + cputime = fire_user_time_account_modifiers(p, cputime); + p->utime = cputime_add(p->utime, cputime); /* Add user time to cpustat. */ @@ -3246,6 +3307,8 @@ struct rq *rq = this_rq(); cputime64_t tmp; + cputime = fire_system_time_account_modifiers(p,hardirq_offset, cputime); + p->stime = cputime_add(p->stime, cputime); /* Add system time to cpustat. */ @@ -6522,6 +6585,9 @@ #ifdef CONFIG_PREEMPT_NOTIFIERS INIT_HLIST_HEAD(&init_task.preempt_notifiers); #endif +#ifdef CONFIG_ACCOUNT_MODIFIERS + INIT_HLIST_HEAD(&init_task.account_modifiers); +#endif #ifdef CONFIG_SMP nr_cpu_ids = highest_cpu + 1;
_______________________________________________ Virtualization mailing list Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/virtualization