846c7bb055
This patch is inspired by the discussion at http://lkml.org/lkml/2007/4/11/187 and implements per cgroup statistics as suggested by Andrew Morton in http://lkml.org/lkml/2007/4/11/263. The patch is on top of 2.6.21-mm1 with Paul's cgroups v9 patches (forward ported) This patch implements per cgroup statistics infrastructure and re-uses code from the taskstats interface. A new set of cgroup operations are registered with commands and attributes. It should be very easy to *extend* per cgroup statistics, by adding members to the cgroupstats structure. The current model for cgroupstats is a pull, a push model (to post statistics on interesting events), should be very easy to add. Currently user space requests for statistics by passing the cgroup file descriptor. Statistics about the state of all the tasks in the cgroup is returned to user space. TODO's/NOTE: This patch provides an infrastructure for implementing cgroup statistics. Based on the needs of each controller, we can incrementally add more statistics, event based support for notification of statistics, accumulation of taskstats into cgroup statistics in the future. Sample output # ./cgroupstats -C /cgroup/a sleeping 2, blocked 0, running 1, stopped 0, uninterruptible 0 # ./cgroupstats -C /cgroup/ sleeping 154, blocked 0, running 0, stopped 0, uninterruptible 0 If the approach looks good, I'll enhance and post the user space utility for the same Feedback, comments, test results are always welcome! [akpm@linux-foundation.org: build fix] Signed-off-by: Balbir Singh <balbir@linux.vnet.ibm.com> Cc: Paul Menage <menage@google.com> Cc: Jay Lan <jlan@engr.sgi.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
134 lines
3.6 KiB
C
134 lines
3.6 KiB
C
/* delayacct.h - per-task delay accounting
|
|
*
|
|
* Copyright (C) Shailabh Nagar, IBM Corp. 2006
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
|
* the GNU General Public License for more details.
|
|
*
|
|
*/
|
|
|
|
#ifndef _LINUX_DELAYACCT_H
|
|
#define _LINUX_DELAYACCT_H
|
|
|
|
#include <linux/sched.h>
|
|
#include <linux/taskstats_kern.h>
|
|
|
|
/*
|
|
* Per-task flags relevant to delay accounting
|
|
* maintained privately to avoid exhausting similar flags in sched.h:PF_*
|
|
* Used to set current->delays->flags
|
|
*/
|
|
#define DELAYACCT_PF_SWAPIN 0x00000001 /* I am doing a swapin */
|
|
#define DELAYACCT_PF_BLKIO 0x00000002 /* I am waiting on IO */
|
|
|
|
#ifdef CONFIG_TASK_DELAY_ACCT
|
|
|
|
extern int delayacct_on; /* Delay accounting turned on/off */
|
|
extern struct kmem_cache *delayacct_cache;
|
|
extern void delayacct_init(void);
|
|
extern void __delayacct_tsk_init(struct task_struct *);
|
|
extern void __delayacct_tsk_exit(struct task_struct *);
|
|
extern void __delayacct_blkio_start(void);
|
|
extern void __delayacct_blkio_end(void);
|
|
extern int __delayacct_add_tsk(struct taskstats *, struct task_struct *);
|
|
extern __u64 __delayacct_blkio_ticks(struct task_struct *);
|
|
|
|
static inline int delayacct_is_task_waiting_on_io(struct task_struct *p)
|
|
{
|
|
if (p->delays)
|
|
return (p->delays->flags & DELAYACCT_PF_BLKIO);
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
static inline void delayacct_set_flag(int flag)
|
|
{
|
|
if (current->delays)
|
|
current->delays->flags |= flag;
|
|
}
|
|
|
|
static inline void delayacct_clear_flag(int flag)
|
|
{
|
|
if (current->delays)
|
|
current->delays->flags &= ~flag;
|
|
}
|
|
|
|
static inline void delayacct_tsk_init(struct task_struct *tsk)
|
|
{
|
|
/* reinitialize in case parent's non-null pointer was dup'ed*/
|
|
tsk->delays = NULL;
|
|
if (delayacct_on)
|
|
__delayacct_tsk_init(tsk);
|
|
}
|
|
|
|
/* Free tsk->delays. Called from bad fork and __put_task_struct
|
|
* where there's no risk of tsk->delays being accessed elsewhere
|
|
*/
|
|
static inline void delayacct_tsk_free(struct task_struct *tsk)
|
|
{
|
|
if (tsk->delays)
|
|
kmem_cache_free(delayacct_cache, tsk->delays);
|
|
tsk->delays = NULL;
|
|
}
|
|
|
|
static inline void delayacct_blkio_start(void)
|
|
{
|
|
delayacct_set_flag(DELAYACCT_PF_BLKIO);
|
|
if (current->delays)
|
|
__delayacct_blkio_start();
|
|
}
|
|
|
|
static inline void delayacct_blkio_end(void)
|
|
{
|
|
if (current->delays)
|
|
__delayacct_blkio_end();
|
|
delayacct_clear_flag(DELAYACCT_PF_BLKIO);
|
|
}
|
|
|
|
static inline int delayacct_add_tsk(struct taskstats *d,
|
|
struct task_struct *tsk)
|
|
{
|
|
if (!delayacct_on || !tsk->delays)
|
|
return 0;
|
|
return __delayacct_add_tsk(d, tsk);
|
|
}
|
|
|
|
static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk)
|
|
{
|
|
if (tsk->delays)
|
|
return __delayacct_blkio_ticks(tsk);
|
|
return 0;
|
|
}
|
|
|
|
#else
|
|
static inline void delayacct_set_flag(int flag)
|
|
{}
|
|
static inline void delayacct_clear_flag(int flag)
|
|
{}
|
|
static inline void delayacct_init(void)
|
|
{}
|
|
static inline void delayacct_tsk_init(struct task_struct *tsk)
|
|
{}
|
|
static inline void delayacct_tsk_free(struct task_struct *tsk)
|
|
{}
|
|
static inline void delayacct_blkio_start(void)
|
|
{}
|
|
static inline void delayacct_blkio_end(void)
|
|
{}
|
|
static inline int delayacct_add_tsk(struct taskstats *d,
|
|
struct task_struct *tsk)
|
|
{ return 0; }
|
|
static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk)
|
|
{ return 0; }
|
|
static inline int delayacct_is_task_waiting_on_io(struct task_struct *p)
|
|
{ return 0; }
|
|
#endif /* CONFIG_TASK_DELAY_ACCT */
|
|
|
|
#endif
|