linux/Documentation/accounting/getdelays.c

539 lines
13 KiB
C
Raw Normal View History

/* getdelays.c
*
* Utility to get per-pid and per-tgid delay accounting statistics
* Also illustrates usage of the taskstats interface
*
* Copyright (C) Shailabh Nagar, IBM Corp. 2005
* Copyright (C) Balbir Singh, IBM Corp. 2006
* Copyright (c) Jay Lan, SGI. 2006
*
* Compile with
* gcc -I/usr/src/linux/include getdelays.c -o getdelays
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <poll.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
delay-accounting: reimplement -c for getdelays.c to report information on a target command Task delay-accounting was identified as one means of determining how long a process spends in congestion_wait() without adding new statistics. For example, if the workload should not be doing IO, delay-accounting could reveal how long it was spending in unexpected IO or delays. Unfortunately, on closer examination it was clear that getdelays does not act as documented. Commit a3baf649 ("per-task-delay-accounting: documentation") added Documentation/accounting/getdelays.c with a -c switch that was documented to fork/exec a child and report statistics on it but for reasons that are unclear to me, commit 9e06d3f9 deleted support for this switch but did not update the documentation. It might be an oversight or it might be because the control flow of the program meant that accounting information would be printed once early in the lifetime of the program making it of limited use. This patch reimplements -c for getdelays.c to act as documented. Unlike the original version, it waits until the command completes before printing any information on it. An example of it being used looks like $ ./getdelays -d -c find /home/mel -name mel print delayacct stats ON /home/mel /home/mel/.notes-wine/drive_c/windows/profiles/mel /home/mel/.wine/drive_c/windows/profiles/mel /home/mel/git-configs/dot.kde/share/apps/konqueror/home/mel PID 5923 CPU count real total virtual total delay total 42779 5051232096 5164722692 564207988 IO count delay total 41727 97804147758 SWAP count delay total 0 0 RECLAIM count delay total 0 0 [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Mel Gorman <mel@csn.ul.ie> Acked-by: Balbir Singh <balbir@in.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-10-28 06:34:42 +08:00
#include <sys/wait.h>
#include <signal.h>
#include <linux/genetlink.h>
#include <linux/taskstats.h>
#include <linux/cgroupstats.h>
/*
* Generic macros for dealing with netlink sockets. Might be duplicated
* elsewhere. It is recommended that commercial grade applications use
* libnl or libnetlink and use the interfaces provided by the library
*/
#define GENLMSG_DATA(glh) ((void *)(NLMSG_DATA(glh) + GENL_HDRLEN))
#define GENLMSG_PAYLOAD(glh) (NLMSG_PAYLOAD(glh, 0) - GENL_HDRLEN)
#define NLA_DATA(na) ((void *)((char*)(na) + NLA_HDRLEN))
#define NLA_PAYLOAD(len) (len - NLA_HDRLEN)
#define err(code, fmt, arg...) \
do { \
fprintf(stderr, fmt, ##arg); \
exit(code); \
} while (0)
int done;
int rcvbufsz;
char name[100];
int dbg;
int print_delays;
[PATCH] io-accounting: add to getdelays Wire up the IO accounting into getdelays.c. Usage: To display I/O stats for each exitting task: vmm:/home/akpm> ./getdelays -m0,1,2,3 -i -l cpumask 0 maskset 1 printing IO accounting listen forever rm: read=8192, write=0, cancelled_write=0 cvs: read=733184, write=4255744, cancelled_write=4096 make: read=217088, write=0, cancelled_write=0 cc1: read=4263936, write=12288, cancelled_write=0 as: read=811008, write=8192, cancelled_write=0 gcc: read=323584, write=0, cancelled_write=12288 cc1: read=0, write=8192, cancelled_write=0 as: read=4096, write=4096, cancelled_write=0 gcc: read=16384, write=0, cancelled_write=4096 as: read=4096, write=4096, cancelled_write=0 gcc: read=16384, write=0, cancelled_write=8192 ld: read=1011712, write=16384, cancelled_write=0 collect2: read=626688, write=0, cancelled_write=0 gcc: read=204800, write=0, cancelled_write=0 cc1: read=0, write=8192, cancelled_write=0 as: read=4096, write=4096, cancelled_write=0 gcc: read=16384, write=0, cancelled_write=8192 ld: read=8192, write=16384, cancelled_write=0 collect2: read=49152, write=0, cancelled_write=0 gcc: read=0, write=0, cancelled_write=0 cc1: read=0, write=4096, cancelled_write=0 ld: read=4096, write=12288, cancelled_write=0 collect2: read=49152, write=0, cancelled_write=0 gcc: read=0, write=0, cancelled_write=0 To display I/O stats for a particular presently-running task: vmm:/home/akpm> ./getdelays -i -p $(pidof crond) printing IO accounting crond: read=61440, write=0, cancelled_write=0 Cc: Jay Lan <jlan@sgi.com> Cc: Shailabh Nagar <nagar@watson.ibm.com> Cc: Balbir Singh <balbir@in.ibm.com> Cc: Chris Sturtivant <csturtiv@sgi.com> Cc: Tony Ernst <tee@sgi.com> Cc: Guillaume Thouvenin <guillaume.thouvenin@bull.net> Cc: David Wright <daw@sgi.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-12-10 18:19:56 +08:00
int print_io_accounting;
int print_task_context_switch_counts;
__u64 stime, utime;
#define PRINTF(fmt, arg...) { \
if (dbg) { \
printf(fmt, ##arg); \
} \
}
/* Maximum size of response requested or message sent */
#define MAX_MSG_SIZE 1024
/* Maximum number of cpus expected to be specified in a cpumask */
#define MAX_CPUS 32
struct msgtemplate {
struct nlmsghdr n;
struct genlmsghdr g;
char buf[MAX_MSG_SIZE];
};
char cpumask[100+6*MAX_CPUS];
static void usage(void)
{
fprintf(stderr, "getdelays [-dilv] [-w logfile] [-r bufsize] "
"[-m cpumask] [-t tgid] [-p pid]\n");
fprintf(stderr, " -d: print delayacct stats\n");
fprintf(stderr, " -i: print IO accounting (works only with -p)\n");
fprintf(stderr, " -l: listen forever\n");
fprintf(stderr, " -v: debug on\n");
fprintf(stderr, " -C: container path\n");
}
/*
* Create a raw netlink socket and bind
*/
static int create_nl_socket(int protocol)
{
int fd;
struct sockaddr_nl local;
fd = socket(AF_NETLINK, SOCK_RAW, protocol);
if (fd < 0)
return -1;
if (rcvbufsz)
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
&rcvbufsz, sizeof(rcvbufsz)) < 0) {
fprintf(stderr, "Unable to set socket rcv buf size "
"to %d\n",
rcvbufsz);
return -1;
}
memset(&local, 0, sizeof(local));
local.nl_family = AF_NETLINK;
if (bind(fd, (struct sockaddr *) &local, sizeof(local)) < 0)
goto error;
return fd;
error:
close(fd);
return -1;
}
static int send_cmd(int sd, __u16 nlmsg_type, __u32 nlmsg_pid,
__u8 genl_cmd, __u16 nla_type,
void *nla_data, int nla_len)
{
struct nlattr *na;
struct sockaddr_nl nladdr;
int r, buflen;
char *buf;
struct msgtemplate msg;
msg.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
msg.n.nlmsg_type = nlmsg_type;
msg.n.nlmsg_flags = NLM_F_REQUEST;
msg.n.nlmsg_seq = 0;
msg.n.nlmsg_pid = nlmsg_pid;
msg.g.cmd = genl_cmd;
msg.g.version = 0x1;
na = (struct nlattr *) GENLMSG_DATA(&msg);
na->nla_type = nla_type;
na->nla_len = nla_len + 1 + NLA_HDRLEN;
memcpy(NLA_DATA(na), nla_data, nla_len);
msg.n.nlmsg_len += NLMSG_ALIGN(na->nla_len);
buf = (char *) &msg;
buflen = msg.n.nlmsg_len ;
memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;
while ((r = sendto(sd, buf, buflen, 0, (struct sockaddr *) &nladdr,
sizeof(nladdr))) < buflen) {
if (r > 0) {
buf += r;
buflen -= r;
} else if (errno != EAGAIN)
return -1;
}
return 0;
}
/*
* Probe the controller in genetlink to find the family id
* for the TASKSTATS family
*/
static int get_family_id(int sd)
{
struct {
struct nlmsghdr n;
struct genlmsghdr g;
char buf[256];
} ans;
int id = 0, rc;
struct nlattr *na;
int rep_len;
strcpy(name, TASKSTATS_GENL_NAME);
rc = send_cmd(sd, GENL_ID_CTRL, getpid(), CTRL_CMD_GETFAMILY,
CTRL_ATTR_FAMILY_NAME, (void *)name,
strlen(TASKSTATS_GENL_NAME)+1);
rep_len = recv(sd, &ans, sizeof(ans), 0);
if (ans.n.nlmsg_type == NLMSG_ERROR ||
(rep_len < 0) || !NLMSG_OK((&ans.n), rep_len))
return 0;
na = (struct nlattr *) GENLMSG_DATA(&ans);
na = (struct nlattr *) ((char *) na + NLA_ALIGN(na->nla_len));
if (na->nla_type == CTRL_ATTR_FAMILY_ID) {
id = *(__u16 *) NLA_DATA(na);
}
return id;
}
static void print_delayacct(struct taskstats *t)
{
printf("\n\nCPU %15s%15s%15s%15s\n"
" %15llu%15llu%15llu%15llu\n"
"IO %15s%15s\n"
" %15llu%15llu\n"
"SWAP %15s%15s\n"
" %15llu%15llu\n"
"RECLAIM %12s%15s\n"
" %15llu%15llu\n",
"count", "real total", "virtual total", "delay total",
docsrc: fix getdelays printk formats Fix printf format type warnings (seen on alpha & ia64): Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 6 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 7 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 8 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 9 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 12 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 13 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 16 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 17 has type '__u64' Documentation/accounting/getdelays.c:214: warning: format '%15llu' expects type 'long long unsigned int', but argument 4 has type '__u64' Documentation/accounting/getdelays.c:214: warning: format '%15llu' expects type 'long long unsigned int', but argument 5 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 2 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 3 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 4 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 5 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 6 has type '__u64' Documentation/accounting/getdelays.c:236: warning: 'cmd_type' may be used uninitialized in this function Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com> Cc: Balbir Singh <balbir@in.ibm.com> Cc: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-08-13 06:09:10 +08:00
(unsigned long long)t->cpu_count,
(unsigned long long)t->cpu_run_real_total,
(unsigned long long)t->cpu_run_virtual_total,
(unsigned long long)t->cpu_delay_total,
"count", "delay total",
docsrc: fix getdelays printk formats Fix printf format type warnings (seen on alpha & ia64): Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 6 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 7 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 8 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 9 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 12 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 13 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 16 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 17 has type '__u64' Documentation/accounting/getdelays.c:214: warning: format '%15llu' expects type 'long long unsigned int', but argument 4 has type '__u64' Documentation/accounting/getdelays.c:214: warning: format '%15llu' expects type 'long long unsigned int', but argument 5 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 2 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 3 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 4 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 5 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 6 has type '__u64' Documentation/accounting/getdelays.c:236: warning: 'cmd_type' may be used uninitialized in this function Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com> Cc: Balbir Singh <balbir@in.ibm.com> Cc: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-08-13 06:09:10 +08:00
(unsigned long long)t->blkio_count,
(unsigned long long)t->blkio_delay_total,
"count", "delay total",
docsrc: fix getdelays printk formats Fix printf format type warnings (seen on alpha & ia64): Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 6 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 7 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 8 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 9 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 12 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 13 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 16 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 17 has type '__u64' Documentation/accounting/getdelays.c:214: warning: format '%15llu' expects type 'long long unsigned int', but argument 4 has type '__u64' Documentation/accounting/getdelays.c:214: warning: format '%15llu' expects type 'long long unsigned int', but argument 5 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 2 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 3 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 4 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 5 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 6 has type '__u64' Documentation/accounting/getdelays.c:236: warning: 'cmd_type' may be used uninitialized in this function Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com> Cc: Balbir Singh <balbir@in.ibm.com> Cc: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-08-13 06:09:10 +08:00
(unsigned long long)t->swapin_count,
(unsigned long long)t->swapin_delay_total,
"count", "delay total",
(unsigned long long)t->freepages_count,
(unsigned long long)t->freepages_delay_total);
}
static void task_context_switch_counts(struct taskstats *t)
{
printf("\n\nTask %15s%15s\n"
" %15llu%15llu\n",
"voluntary", "nonvoluntary",
docsrc: fix getdelays printk formats Fix printf format type warnings (seen on alpha & ia64): Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 6 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 7 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 8 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 9 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 12 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 13 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 16 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 17 has type '__u64' Documentation/accounting/getdelays.c:214: warning: format '%15llu' expects type 'long long unsigned int', but argument 4 has type '__u64' Documentation/accounting/getdelays.c:214: warning: format '%15llu' expects type 'long long unsigned int', but argument 5 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 2 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 3 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 4 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 5 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 6 has type '__u64' Documentation/accounting/getdelays.c:236: warning: 'cmd_type' may be used uninitialized in this function Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com> Cc: Balbir Singh <balbir@in.ibm.com> Cc: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-08-13 06:09:10 +08:00
(unsigned long long)t->nvcsw, (unsigned long long)t->nivcsw);
}
static void print_cgroupstats(struct cgroupstats *c)
{
printf("sleeping %llu, blocked %llu, running %llu, stopped %llu, "
docsrc: fix getdelays printk formats Fix printf format type warnings (seen on alpha & ia64): Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 6 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 7 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 8 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 9 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 12 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 13 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 16 has type '__u64' Documentation/accounting/getdelays.c:206: warning: format '%15llu' expects type 'long long unsigned int', but argument 17 has type '__u64' Documentation/accounting/getdelays.c:214: warning: format '%15llu' expects type 'long long unsigned int', but argument 4 has type '__u64' Documentation/accounting/getdelays.c:214: warning: format '%15llu' expects type 'long long unsigned int', but argument 5 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 2 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 3 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 4 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 5 has type '__u64' Documentation/accounting/getdelays.c:221: warning: format '%llu' expects type 'long long unsigned int', but argument 6 has type '__u64' Documentation/accounting/getdelays.c:236: warning: 'cmd_type' may be used uninitialized in this function Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com> Cc: Balbir Singh <balbir@in.ibm.com> Cc: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2008-08-13 06:09:10 +08:00
"uninterruptible %llu\n", (unsigned long long)c->nr_sleeping,
(unsigned long long)c->nr_io_wait,
(unsigned long long)c->nr_running,
(unsigned long long)c->nr_stopped,
(unsigned long long)c->nr_uninterruptible);
}
static void print_ioacct(struct taskstats *t)
[PATCH] io-accounting: add to getdelays Wire up the IO accounting into getdelays.c. Usage: To display I/O stats for each exitting task: vmm:/home/akpm> ./getdelays -m0,1,2,3 -i -l cpumask 0 maskset 1 printing IO accounting listen forever rm: read=8192, write=0, cancelled_write=0 cvs: read=733184, write=4255744, cancelled_write=4096 make: read=217088, write=0, cancelled_write=0 cc1: read=4263936, write=12288, cancelled_write=0 as: read=811008, write=8192, cancelled_write=0 gcc: read=323584, write=0, cancelled_write=12288 cc1: read=0, write=8192, cancelled_write=0 as: read=4096, write=4096, cancelled_write=0 gcc: read=16384, write=0, cancelled_write=4096 as: read=4096, write=4096, cancelled_write=0 gcc: read=16384, write=0, cancelled_write=8192 ld: read=1011712, write=16384, cancelled_write=0 collect2: read=626688, write=0, cancelled_write=0 gcc: read=204800, write=0, cancelled_write=0 cc1: read=0, write=8192, cancelled_write=0 as: read=4096, write=4096, cancelled_write=0 gcc: read=16384, write=0, cancelled_write=8192 ld: read=8192, write=16384, cancelled_write=0 collect2: read=49152, write=0, cancelled_write=0 gcc: read=0, write=0, cancelled_write=0 cc1: read=0, write=4096, cancelled_write=0 ld: read=4096, write=12288, cancelled_write=0 collect2: read=49152, write=0, cancelled_write=0 gcc: read=0, write=0, cancelled_write=0 To display I/O stats for a particular presently-running task: vmm:/home/akpm> ./getdelays -i -p $(pidof crond) printing IO accounting crond: read=61440, write=0, cancelled_write=0 Cc: Jay Lan <jlan@sgi.com> Cc: Shailabh Nagar <nagar@watson.ibm.com> Cc: Balbir Singh <balbir@in.ibm.com> Cc: Chris Sturtivant <csturtiv@sgi.com> Cc: Tony Ernst <tee@sgi.com> Cc: Guillaume Thouvenin <guillaume.thouvenin@bull.net> Cc: David Wright <daw@sgi.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-12-10 18:19:56 +08:00
{
printf("%s: read=%llu, write=%llu, cancelled_write=%llu\n",
t->ac_comm,
(unsigned long long)t->read_bytes,
(unsigned long long)t->write_bytes,
(unsigned long long)t->cancelled_write_bytes);
}
int main(int argc, char *argv[])
{
int c, rc, rep_len, aggr_len, len2;
int cmd_type = TASKSTATS_CMD_ATTR_UNSPEC;
__u16 id;
__u32 mypid;
struct nlattr *na;
int nl_sd = -1;
int len = 0;
pid_t tid = 0;
pid_t rtid = 0;
int fd = 0;
int count = 0;
int write_file = 0;
int maskset = 0;
char *logfile = NULL;
int loop = 0;
int containerset = 0;
char containerpath[1024];
int cfd = 0;
delay-accounting: reimplement -c for getdelays.c to report information on a target command Task delay-accounting was identified as one means of determining how long a process spends in congestion_wait() without adding new statistics. For example, if the workload should not be doing IO, delay-accounting could reveal how long it was spending in unexpected IO or delays. Unfortunately, on closer examination it was clear that getdelays does not act as documented. Commit a3baf649 ("per-task-delay-accounting: documentation") added Documentation/accounting/getdelays.c with a -c switch that was documented to fork/exec a child and report statistics on it but for reasons that are unclear to me, commit 9e06d3f9 deleted support for this switch but did not update the documentation. It might be an oversight or it might be because the control flow of the program meant that accounting information would be printed once early in the lifetime of the program making it of limited use. This patch reimplements -c for getdelays.c to act as documented. Unlike the original version, it waits until the command completes before printing any information on it. An example of it being used looks like $ ./getdelays -d -c find /home/mel -name mel print delayacct stats ON /home/mel /home/mel/.notes-wine/drive_c/windows/profiles/mel /home/mel/.wine/drive_c/windows/profiles/mel /home/mel/git-configs/dot.kde/share/apps/konqueror/home/mel PID 5923 CPU count real total virtual total delay total 42779 5051232096 5164722692 564207988 IO count delay total 41727 97804147758 SWAP count delay total 0 0 RECLAIM count delay total 0 0 [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Mel Gorman <mel@csn.ul.ie> Acked-by: Balbir Singh <balbir@in.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-10-28 06:34:42 +08:00
int forking = 0;
sigset_t sigset;
struct msgtemplate msg;
delay-accounting: reimplement -c for getdelays.c to report information on a target command Task delay-accounting was identified as one means of determining how long a process spends in congestion_wait() without adding new statistics. For example, if the workload should not be doing IO, delay-accounting could reveal how long it was spending in unexpected IO or delays. Unfortunately, on closer examination it was clear that getdelays does not act as documented. Commit a3baf649 ("per-task-delay-accounting: documentation") added Documentation/accounting/getdelays.c with a -c switch that was documented to fork/exec a child and report statistics on it but for reasons that are unclear to me, commit 9e06d3f9 deleted support for this switch but did not update the documentation. It might be an oversight or it might be because the control flow of the program meant that accounting information would be printed once early in the lifetime of the program making it of limited use. This patch reimplements -c for getdelays.c to act as documented. Unlike the original version, it waits until the command completes before printing any information on it. An example of it being used looks like $ ./getdelays -d -c find /home/mel -name mel print delayacct stats ON /home/mel /home/mel/.notes-wine/drive_c/windows/profiles/mel /home/mel/.wine/drive_c/windows/profiles/mel /home/mel/git-configs/dot.kde/share/apps/konqueror/home/mel PID 5923 CPU count real total virtual total delay total 42779 5051232096 5164722692 564207988 IO count delay total 41727 97804147758 SWAP count delay total 0 0 RECLAIM count delay total 0 0 [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Mel Gorman <mel@csn.ul.ie> Acked-by: Balbir Singh <balbir@in.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-10-28 06:34:42 +08:00
while (!forking) {
c = getopt(argc, argv, "qdiw:r:m:t:p:vlC:c:");
if (c < 0)
break;
switch (c) {
case 'd':
printf("print delayacct stats ON\n");
print_delays = 1;
break;
[PATCH] io-accounting: add to getdelays Wire up the IO accounting into getdelays.c. Usage: To display I/O stats for each exitting task: vmm:/home/akpm> ./getdelays -m0,1,2,3 -i -l cpumask 0 maskset 1 printing IO accounting listen forever rm: read=8192, write=0, cancelled_write=0 cvs: read=733184, write=4255744, cancelled_write=4096 make: read=217088, write=0, cancelled_write=0 cc1: read=4263936, write=12288, cancelled_write=0 as: read=811008, write=8192, cancelled_write=0 gcc: read=323584, write=0, cancelled_write=12288 cc1: read=0, write=8192, cancelled_write=0 as: read=4096, write=4096, cancelled_write=0 gcc: read=16384, write=0, cancelled_write=4096 as: read=4096, write=4096, cancelled_write=0 gcc: read=16384, write=0, cancelled_write=8192 ld: read=1011712, write=16384, cancelled_write=0 collect2: read=626688, write=0, cancelled_write=0 gcc: read=204800, write=0, cancelled_write=0 cc1: read=0, write=8192, cancelled_write=0 as: read=4096, write=4096, cancelled_write=0 gcc: read=16384, write=0, cancelled_write=8192 ld: read=8192, write=16384, cancelled_write=0 collect2: read=49152, write=0, cancelled_write=0 gcc: read=0, write=0, cancelled_write=0 cc1: read=0, write=4096, cancelled_write=0 ld: read=4096, write=12288, cancelled_write=0 collect2: read=49152, write=0, cancelled_write=0 gcc: read=0, write=0, cancelled_write=0 To display I/O stats for a particular presently-running task: vmm:/home/akpm> ./getdelays -i -p $(pidof crond) printing IO accounting crond: read=61440, write=0, cancelled_write=0 Cc: Jay Lan <jlan@sgi.com> Cc: Shailabh Nagar <nagar@watson.ibm.com> Cc: Balbir Singh <balbir@in.ibm.com> Cc: Chris Sturtivant <csturtiv@sgi.com> Cc: Tony Ernst <tee@sgi.com> Cc: Guillaume Thouvenin <guillaume.thouvenin@bull.net> Cc: David Wright <daw@sgi.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-12-10 18:19:56 +08:00
case 'i':
printf("printing IO accounting\n");
print_io_accounting = 1;
break;
case 'q':
printf("printing task/process context switch rates\n");
print_task_context_switch_counts = 1;
break;
case 'C':
containerset = 1;
strncpy(containerpath, optarg, strlen(optarg) + 1);
break;
case 'w':
logfile = strdup(optarg);
printf("write to file %s\n", logfile);
write_file = 1;
break;
case 'r':
rcvbufsz = atoi(optarg);
printf("receive buf size %d\n", rcvbufsz);
if (rcvbufsz < 0)
err(1, "Invalid rcv buf size\n");
break;
case 'm':
strncpy(cpumask, optarg, sizeof(cpumask));
maskset = 1;
printf("cpumask %s maskset %d\n", cpumask, maskset);
break;
case 't':
tid = atoi(optarg);
if (!tid)
err(1, "Invalid tgid\n");
cmd_type = TASKSTATS_CMD_ATTR_TGID;
break;
case 'p':
tid = atoi(optarg);
if (!tid)
err(1, "Invalid pid\n");
cmd_type = TASKSTATS_CMD_ATTR_PID;
break;
delay-accounting: reimplement -c for getdelays.c to report information on a target command Task delay-accounting was identified as one means of determining how long a process spends in congestion_wait() without adding new statistics. For example, if the workload should not be doing IO, delay-accounting could reveal how long it was spending in unexpected IO or delays. Unfortunately, on closer examination it was clear that getdelays does not act as documented. Commit a3baf649 ("per-task-delay-accounting: documentation") added Documentation/accounting/getdelays.c with a -c switch that was documented to fork/exec a child and report statistics on it but for reasons that are unclear to me, commit 9e06d3f9 deleted support for this switch but did not update the documentation. It might be an oversight or it might be because the control flow of the program meant that accounting information would be printed once early in the lifetime of the program making it of limited use. This patch reimplements -c for getdelays.c to act as documented. Unlike the original version, it waits until the command completes before printing any information on it. An example of it being used looks like $ ./getdelays -d -c find /home/mel -name mel print delayacct stats ON /home/mel /home/mel/.notes-wine/drive_c/windows/profiles/mel /home/mel/.wine/drive_c/windows/profiles/mel /home/mel/git-configs/dot.kde/share/apps/konqueror/home/mel PID 5923 CPU count real total virtual total delay total 42779 5051232096 5164722692 564207988 IO count delay total 41727 97804147758 SWAP count delay total 0 0 RECLAIM count delay total 0 0 [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Mel Gorman <mel@csn.ul.ie> Acked-by: Balbir Singh <balbir@in.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-10-28 06:34:42 +08:00
case 'c':
/* Block SIGCHLD for sigwait() later */
if (sigemptyset(&sigset) == -1)
err(1, "Failed to empty sigset");
if (sigaddset(&sigset, SIGCHLD))
err(1, "Failed to set sigchld in sigset");
sigprocmask(SIG_BLOCK, &sigset, NULL);
/* fork/exec a child */
tid = fork();
if (tid < 0)
err(1, "Fork failed\n");
if (tid == 0)
if (execvp(argv[optind - 1],
&argv[optind - 1]) < 0)
exit(-1);
/* Set the command type and avoid further processing */
cmd_type = TASKSTATS_CMD_ATTR_PID;
forking = 1;
break;
case 'v':
printf("debug on\n");
dbg = 1;
break;
case 'l':
printf("listen forever\n");
loop = 1;
break;
default:
usage();
exit(-1);
}
}
if (write_file) {
fd = open(logfile, O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (fd == -1) {
perror("Cannot open output file\n");
exit(1);
}
}
if ((nl_sd = create_nl_socket(NETLINK_GENERIC)) < 0)
err(1, "error creating Netlink socket\n");
mypid = getpid();
id = get_family_id(nl_sd);
if (!id) {
fprintf(stderr, "Error getting family id, errno %d\n", errno);
goto err;
}
PRINTF("family id %d\n", id);
if (maskset) {
rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
TASKSTATS_CMD_ATTR_REGISTER_CPUMASK,
&cpumask, strlen(cpumask) + 1);
PRINTF("Sent register cpumask, retval %d\n", rc);
if (rc < 0) {
fprintf(stderr, "error sending register cpumask\n");
goto err;
}
}
if (tid && containerset) {
fprintf(stderr, "Select either -t or -C, not both\n");
goto err;
}
delay-accounting: reimplement -c for getdelays.c to report information on a target command Task delay-accounting was identified as one means of determining how long a process spends in congestion_wait() without adding new statistics. For example, if the workload should not be doing IO, delay-accounting could reveal how long it was spending in unexpected IO or delays. Unfortunately, on closer examination it was clear that getdelays does not act as documented. Commit a3baf649 ("per-task-delay-accounting: documentation") added Documentation/accounting/getdelays.c with a -c switch that was documented to fork/exec a child and report statistics on it but for reasons that are unclear to me, commit 9e06d3f9 deleted support for this switch but did not update the documentation. It might be an oversight or it might be because the control flow of the program meant that accounting information would be printed once early in the lifetime of the program making it of limited use. This patch reimplements -c for getdelays.c to act as documented. Unlike the original version, it waits until the command completes before printing any information on it. An example of it being used looks like $ ./getdelays -d -c find /home/mel -name mel print delayacct stats ON /home/mel /home/mel/.notes-wine/drive_c/windows/profiles/mel /home/mel/.wine/drive_c/windows/profiles/mel /home/mel/git-configs/dot.kde/share/apps/konqueror/home/mel PID 5923 CPU count real total virtual total delay total 42779 5051232096 5164722692 564207988 IO count delay total 41727 97804147758 SWAP count delay total 0 0 RECLAIM count delay total 0 0 [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Mel Gorman <mel@csn.ul.ie> Acked-by: Balbir Singh <balbir@in.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-10-28 06:34:42 +08:00
/*
* If we forked a child, wait for it to exit. Cannot use waitpid()
* as all the delicious data would be reaped as part of the wait
*/
if (tid && forking) {
int sig_received;
sigwait(&sigset, &sig_received);
}
if (tid) {
rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
cmd_type, &tid, sizeof(__u32));
PRINTF("Sent pid/tgid, retval %d\n", rc);
if (rc < 0) {
fprintf(stderr, "error sending tid/tgid cmd\n");
goto done;
}
}
if (containerset) {
cfd = open(containerpath, O_RDONLY);
if (cfd < 0) {
perror("error opening container file");
goto err;
}
rc = send_cmd(nl_sd, id, mypid, CGROUPSTATS_CMD_GET,
CGROUPSTATS_CMD_ATTR_FD, &cfd, sizeof(__u32));
if (rc < 0) {
perror("error sending cgroupstats command");
goto err;
}
}
if (!maskset && !tid && !containerset) {
usage();
goto err;
}
do {
rep_len = recv(nl_sd, &msg, sizeof(msg), 0);
PRINTF("received %d bytes\n", rep_len);
if (rep_len < 0) {
fprintf(stderr, "nonfatal reply error: errno %d\n",
errno);
continue;
}
if (msg.n.nlmsg_type == NLMSG_ERROR ||
!NLMSG_OK((&msg.n), rep_len)) {
struct nlmsgerr *err = NLMSG_DATA(&msg);
fprintf(stderr, "fatal reply error, errno %d\n",
err->error);
goto done;
}
PRINTF("nlmsghdr size=%zu, nlmsg_len=%d, rep_len=%d\n",
sizeof(struct nlmsghdr), msg.n.nlmsg_len, rep_len);
rep_len = GENLMSG_PAYLOAD(&msg.n);
na = (struct nlattr *) GENLMSG_DATA(&msg);
len = 0;
while (len < rep_len) {
len += NLA_ALIGN(na->nla_len);
switch (na->nla_type) {
case TASKSTATS_TYPE_AGGR_TGID:
/* Fall through */
case TASKSTATS_TYPE_AGGR_PID:
aggr_len = NLA_PAYLOAD(na->nla_len);
len2 = 0;
/* For nested attributes, na follows */
na = (struct nlattr *) NLA_DATA(na);
done = 0;
while (len2 < aggr_len) {
switch (na->nla_type) {
case TASKSTATS_TYPE_PID:
rtid = *(int *) NLA_DATA(na);
if (print_delays)
printf("PID\t%d\n", rtid);
break;
case TASKSTATS_TYPE_TGID:
rtid = *(int *) NLA_DATA(na);
if (print_delays)
printf("TGID\t%d\n", rtid);
break;
case TASKSTATS_TYPE_STATS:
count++;
if (print_delays)
print_delayacct((struct taskstats *) NLA_DATA(na));
[PATCH] io-accounting: add to getdelays Wire up the IO accounting into getdelays.c. Usage: To display I/O stats for each exitting task: vmm:/home/akpm> ./getdelays -m0,1,2,3 -i -l cpumask 0 maskset 1 printing IO accounting listen forever rm: read=8192, write=0, cancelled_write=0 cvs: read=733184, write=4255744, cancelled_write=4096 make: read=217088, write=0, cancelled_write=0 cc1: read=4263936, write=12288, cancelled_write=0 as: read=811008, write=8192, cancelled_write=0 gcc: read=323584, write=0, cancelled_write=12288 cc1: read=0, write=8192, cancelled_write=0 as: read=4096, write=4096, cancelled_write=0 gcc: read=16384, write=0, cancelled_write=4096 as: read=4096, write=4096, cancelled_write=0 gcc: read=16384, write=0, cancelled_write=8192 ld: read=1011712, write=16384, cancelled_write=0 collect2: read=626688, write=0, cancelled_write=0 gcc: read=204800, write=0, cancelled_write=0 cc1: read=0, write=8192, cancelled_write=0 as: read=4096, write=4096, cancelled_write=0 gcc: read=16384, write=0, cancelled_write=8192 ld: read=8192, write=16384, cancelled_write=0 collect2: read=49152, write=0, cancelled_write=0 gcc: read=0, write=0, cancelled_write=0 cc1: read=0, write=4096, cancelled_write=0 ld: read=4096, write=12288, cancelled_write=0 collect2: read=49152, write=0, cancelled_write=0 gcc: read=0, write=0, cancelled_write=0 To display I/O stats for a particular presently-running task: vmm:/home/akpm> ./getdelays -i -p $(pidof crond) printing IO accounting crond: read=61440, write=0, cancelled_write=0 Cc: Jay Lan <jlan@sgi.com> Cc: Shailabh Nagar <nagar@watson.ibm.com> Cc: Balbir Singh <balbir@in.ibm.com> Cc: Chris Sturtivant <csturtiv@sgi.com> Cc: Tony Ernst <tee@sgi.com> Cc: Guillaume Thouvenin <guillaume.thouvenin@bull.net> Cc: David Wright <daw@sgi.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-12-10 18:19:56 +08:00
if (print_io_accounting)
print_ioacct((struct taskstats *) NLA_DATA(na));
if (print_task_context_switch_counts)
task_context_switch_counts((struct taskstats *) NLA_DATA(na));
if (fd) {
if (write(fd, NLA_DATA(na), na->nla_len) < 0) {
err(1,"write error\n");
}
}
if (!loop)
goto done;
break;
default:
fprintf(stderr, "Unknown nested"
" nla_type %d\n",
na->nla_type);
break;
}
len2 += NLA_ALIGN(na->nla_len);
na = (struct nlattr *) ((char *) na + len2);
}
break;
case CGROUPSTATS_TYPE_CGROUP_STATS:
print_cgroupstats(NLA_DATA(na));
break;
default:
fprintf(stderr, "Unknown nla_type %d\n",
na->nla_type);
taskstats: pad taskstats netlink response for aligment issues on ia64 The taskstats structure is internally aligned on 8 byte boundaries but the layout of the aggregrate reply, with two NLA headers and the pid (each 4 bytes), actually force the entire structure to be unaligned. This causes the kernel to issue unaligned access warnings on some architectures like ia64. Unfortunately, some software out there doesn't properly unroll the NLA packet and assumes that the start of the taskstats structure will always be 20 bytes from the start of the netlink payload. Aligning the start of the taskstats structure breaks this software, which we don't want. So, for now the alignment only happens on architectures that require it and those users will have to update to fixed versions of those packages. Space is reserved in the packet only when needed. This ifdef should be removed in several years e.g. 2012 once we can be confident that fixed versions are installed on most systems. We add the padding before the aggregate since the aggregate is already a defined type. Commit 85893120 ("delayacct: align to 8 byte boundary on 64-bit systems") previously addressed the alignment issues by padding out the pid field. This was supposed to be a compatible change but the circumstances described above mean that it wasn't. This patch backs out that change, since it was a hack, and introduces a new NULL attribute type to provide the padding. Padding the response with 4 bytes avoids allocating an aligned taskstats structure and copying it back. Since the structure weighs in at 328 bytes, it's too big to do it on the stack. Signed-off-by: Jeff Mahoney <jeffm@suse.com> Reported-by: Brian Rogers <brian@xyzw.org> Cc: Jeff Mahoney <jeffm@suse.com> Cc: Guillaume Chazarain <guichaz@gmail.com> Cc: Balbir Singh <balbir@in.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-12-22 09:24:30 +08:00
case TASKSTATS_TYPE_NULL:
break;
}
na = (struct nlattr *) (GENLMSG_DATA(&msg) + len);
}
} while (loop);
done:
if (maskset) {
rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK,
&cpumask, strlen(cpumask) + 1);
printf("Sent deregister mask, retval %d\n", rc);
if (rc < 0)
err(rc, "error sending deregister cpumask\n");
}
err:
close(nl_sd);
if (fd)
close(fd);
if (cfd)
close(cfd);
return 0;
}