Commit db9e5679 authored by Mel Gorman's avatar Mel Gorman Committed by Linus Torvalds

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: default avatarMel Gorman <mel@csn.ul.ie>
Acked-by: default avatarBalbir Singh <balbir@in.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 7af37bec
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/wait.h>
#include <signal.h> #include <signal.h>
#include <linux/genetlink.h> #include <linux/genetlink.h>
...@@ -266,11 +267,13 @@ int main(int argc, char *argv[]) ...@@ -266,11 +267,13 @@ int main(int argc, char *argv[])
int containerset = 0; int containerset = 0;
char containerpath[1024]; char containerpath[1024];
int cfd = 0; int cfd = 0;
int forking = 0;
sigset_t sigset;
struct msgtemplate msg; struct msgtemplate msg;
while (1) { while (!forking) {
c = getopt(argc, argv, "qdiw:r:m:t:p:vlC:"); c = getopt(argc, argv, "qdiw:r:m:t:p:vlC:c:");
if (c < 0) if (c < 0)
break; break;
...@@ -319,6 +322,28 @@ int main(int argc, char *argv[]) ...@@ -319,6 +322,28 @@ int main(int argc, char *argv[])
err(1, "Invalid pid\n"); err(1, "Invalid pid\n");
cmd_type = TASKSTATS_CMD_ATTR_PID; cmd_type = TASKSTATS_CMD_ATTR_PID;
break; break;
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': case 'v':
printf("debug on\n"); printf("debug on\n");
dbg = 1; dbg = 1;
...@@ -370,6 +395,15 @@ int main(int argc, char *argv[]) ...@@ -370,6 +395,15 @@ int main(int argc, char *argv[])
goto err; goto err;
} }
/*
* 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) { if (tid) {
rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET, rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
cmd_type, &tid, sizeof(__u32)); cmd_type, &tid, sizeof(__u32));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment