^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* getdelays.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Utility to get per-pid and per-tgid delay accounting statistics
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Also illustrates usage of the taskstats interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) Shailabh Nagar, IBM Corp. 2005
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) Balbir Singh, IBM Corp. 2006
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (c) Jay Lan, SGI. 2006
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Compile with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * gcc -I/usr/src/linux/include getdelays.c -o getdelays
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <poll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <sys/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <sys/socket.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <sys/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/genetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/taskstats.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/cgroupstats.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * Generic macros for dealing with netlink sockets. Might be duplicated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * elsewhere. It is recommended that commercial grade applications use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * libnl or libnetlink and use the interfaces provided by the library
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define GENLMSG_DATA(glh) ((void *)(NLMSG_DATA(glh) + GENL_HDRLEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define GENLMSG_PAYLOAD(glh) (NLMSG_PAYLOAD(glh, 0) - GENL_HDRLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define NLA_DATA(na) ((void *)((char*)(na) + NLA_HDRLEN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define NLA_PAYLOAD(len) (len - NLA_HDRLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define err(code, fmt, arg...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) fprintf(stderr, fmt, ##arg); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) exit(code); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) int done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) int rcvbufsz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) char name[100];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) int dbg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) int print_delays;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) int print_io_accounting;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) int print_task_context_switch_counts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define PRINTF(fmt, arg...) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (dbg) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) printf(fmt, ##arg); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* Maximum size of response requested or message sent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define MAX_MSG_SIZE 1024
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* Maximum number of cpus expected to be specified in a cpumask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define MAX_CPUS 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct msgtemplate {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct nlmsghdr n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct genlmsghdr g;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) char buf[MAX_MSG_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) char cpumask[100+6*MAX_CPUS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static void usage(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) fprintf(stderr, "getdelays [-dilv] [-w logfile] [-r bufsize] "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) "[-m cpumask] [-t tgid] [-p pid]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) fprintf(stderr, " -d: print delayacct stats\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) fprintf(stderr, " -i: print IO accounting (works only with -p)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) fprintf(stderr, " -l: listen forever\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) fprintf(stderr, " -v: debug on\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) fprintf(stderr, " -C: container path\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * Create a raw netlink socket and bind
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static int create_nl_socket(int protocol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) int fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct sockaddr_nl local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) fd = socket(AF_NETLINK, SOCK_RAW, protocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (rcvbufsz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) &rcvbufsz, sizeof(rcvbufsz)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) fprintf(stderr, "Unable to set socket rcv buf size to %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) rcvbufsz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) memset(&local, 0, sizeof(local));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) local.nl_family = AF_NETLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (bind(fd, (struct sockaddr *) &local, sizeof(local)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) static int send_cmd(int sd, __u16 nlmsg_type, __u32 nlmsg_pid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) __u8 genl_cmd, __u16 nla_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) void *nla_data, int nla_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct nlattr *na;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct sockaddr_nl nladdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) int r, buflen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct msgtemplate msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) msg.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) msg.n.nlmsg_type = nlmsg_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) msg.n.nlmsg_flags = NLM_F_REQUEST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) msg.n.nlmsg_seq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) msg.n.nlmsg_pid = nlmsg_pid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) msg.g.cmd = genl_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) msg.g.version = 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) na = (struct nlattr *) GENLMSG_DATA(&msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) na->nla_type = nla_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) na->nla_len = nla_len + NLA_HDRLEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) memcpy(NLA_DATA(na), nla_data, nla_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) msg.n.nlmsg_len += NLMSG_ALIGN(na->nla_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) buf = (char *) &msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) buflen = msg.n.nlmsg_len ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) memset(&nladdr, 0, sizeof(nladdr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) nladdr.nl_family = AF_NETLINK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) while ((r = sendto(sd, buf, buflen, 0, (struct sockaddr *) &nladdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) sizeof(nladdr))) < buflen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if (r > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) buf += r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) buflen -= r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) } else if (errno != EAGAIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * Probe the controller in genetlink to find the family id
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * for the TASKSTATS family
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static int get_family_id(int sd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct nlmsghdr n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct genlmsghdr g;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) char buf[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) } ans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) int id = 0, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct nlattr *na;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) int rep_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) strcpy(name, TASKSTATS_GENL_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) rc = send_cmd(sd, GENL_ID_CTRL, getpid(), CTRL_CMD_GETFAMILY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) CTRL_ATTR_FAMILY_NAME, (void *)name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) strlen(TASKSTATS_GENL_NAME)+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return 0; /* sendto() failure? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) rep_len = recv(sd, &ans, sizeof(ans), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (ans.n.nlmsg_type == NLMSG_ERROR ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) (rep_len < 0) || !NLMSG_OK((&ans.n), rep_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) na = (struct nlattr *) GENLMSG_DATA(&ans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) na = (struct nlattr *) ((char *) na + NLA_ALIGN(na->nla_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (na->nla_type == CTRL_ATTR_FAMILY_ID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) id = *(__u16 *) NLA_DATA(na);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) #define average_ms(t, c) (t / 1000000ULL / (c ? c : 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static void print_delayacct(struct taskstats *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) printf("\n\nCPU %15s%15s%15s%15s%15s\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) " %15llu%15llu%15llu%15llu%15.3fms\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) "IO %15s%15s%15s\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) " %15llu%15llu%15llums\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) "SWAP %15s%15s%15s\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) " %15llu%15llu%15llums\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) "RECLAIM %12s%15s%15s\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) " %15llu%15llu%15llums\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) "THRASHING%12s%15s%15s\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) " %15llu%15llu%15llums\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) "count", "real total", "virtual total",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) "delay total", "delay average",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) (unsigned long long)t->cpu_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) (unsigned long long)t->cpu_run_real_total,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) (unsigned long long)t->cpu_run_virtual_total,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) (unsigned long long)t->cpu_delay_total,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) average_ms((double)t->cpu_delay_total, t->cpu_count),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) "count", "delay total", "delay average",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) (unsigned long long)t->blkio_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) (unsigned long long)t->blkio_delay_total,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) average_ms(t->blkio_delay_total, t->blkio_count),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) "count", "delay total", "delay average",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) (unsigned long long)t->swapin_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) (unsigned long long)t->swapin_delay_total,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) average_ms(t->swapin_delay_total, t->swapin_count),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) "count", "delay total", "delay average",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) (unsigned long long)t->freepages_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) (unsigned long long)t->freepages_delay_total,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) average_ms(t->freepages_delay_total, t->freepages_count),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) "count", "delay total", "delay average",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) (unsigned long long)t->thrashing_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) (unsigned long long)t->thrashing_delay_total,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) average_ms(t->thrashing_delay_total, t->thrashing_count));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) static void task_context_switch_counts(struct taskstats *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) printf("\n\nTask %15s%15s\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) " %15llu%15llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) "voluntary", "nonvoluntary",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) (unsigned long long)t->nvcsw, (unsigned long long)t->nivcsw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static void print_cgroupstats(struct cgroupstats *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) printf("sleeping %llu, blocked %llu, running %llu, stopped %llu, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) "uninterruptible %llu\n", (unsigned long long)c->nr_sleeping,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) (unsigned long long)c->nr_io_wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) (unsigned long long)c->nr_running,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) (unsigned long long)c->nr_stopped,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) (unsigned long long)c->nr_uninterruptible);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static void print_ioacct(struct taskstats *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) printf("%s: read=%llu, write=%llu, cancelled_write=%llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) t->ac_comm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) (unsigned long long)t->read_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) (unsigned long long)t->write_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) (unsigned long long)t->cancelled_write_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) int main(int argc, char *argv[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) int c, rc, rep_len, aggr_len, len2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) int cmd_type = TASKSTATS_CMD_ATTR_UNSPEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) __u16 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) __u32 mypid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) struct nlattr *na;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) int nl_sd = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) int len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) pid_t tid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) pid_t rtid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) int fd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) int count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) int write_file = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) int maskset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) char *logfile = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) int loop = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) int containerset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) char *containerpath = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) int cfd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) int forking = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) sigset_t sigset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) struct msgtemplate msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) while (!forking) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) c = getopt(argc, argv, "qdiw:r:m:t:p:vlC:c:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (c < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) switch (c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) case 'd':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) printf("print delayacct stats ON\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) print_delays = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) case 'i':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) printf("printing IO accounting\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) print_io_accounting = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) case 'q':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) printf("printing task/process context switch rates\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) print_task_context_switch_counts = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) case 'C':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) containerset = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) containerpath = optarg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) case 'w':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) logfile = strdup(optarg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) printf("write to file %s\n", logfile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) write_file = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) case 'r':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) rcvbufsz = atoi(optarg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) printf("receive buf size %d\n", rcvbufsz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (rcvbufsz < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) err(1, "Invalid rcv buf size\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) case 'm':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) strncpy(cpumask, optarg, sizeof(cpumask));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) cpumask[sizeof(cpumask) - 1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) maskset = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) printf("cpumask %s maskset %d\n", cpumask, maskset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) case 't':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) tid = atoi(optarg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (!tid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) err(1, "Invalid tgid\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) cmd_type = TASKSTATS_CMD_ATTR_TGID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) case 'p':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) tid = atoi(optarg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (!tid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) err(1, "Invalid pid\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) cmd_type = TASKSTATS_CMD_ATTR_PID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) case 'c':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) /* Block SIGCHLD for sigwait() later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (sigemptyset(&sigset) == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) err(1, "Failed to empty sigset");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (sigaddset(&sigset, SIGCHLD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) err(1, "Failed to set sigchld in sigset");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) sigprocmask(SIG_BLOCK, &sigset, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) /* fork/exec a child */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) tid = fork();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (tid < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) err(1, "Fork failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (tid == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (execvp(argv[optind - 1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) &argv[optind - 1]) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) exit(-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) /* Set the command type and avoid further processing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) cmd_type = TASKSTATS_CMD_ATTR_PID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) forking = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) case 'v':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) printf("debug on\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) dbg = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) case 'l':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) printf("listen forever\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) loop = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) usage();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) exit(-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (write_file) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) fd = open(logfile, O_WRONLY | O_CREAT | O_TRUNC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (fd == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) perror("Cannot open output file\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) exit(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) nl_sd = create_nl_socket(NETLINK_GENERIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (nl_sd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) err(1, "error creating Netlink socket\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) mypid = getpid();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) id = get_family_id(nl_sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (!id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) fprintf(stderr, "Error getting family id, errno %d\n", errno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) PRINTF("family id %d\n", id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (maskset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) TASKSTATS_CMD_ATTR_REGISTER_CPUMASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) &cpumask, strlen(cpumask) + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) PRINTF("Sent register cpumask, retval %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) fprintf(stderr, "error sending register cpumask\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (tid && containerset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) fprintf(stderr, "Select either -t or -C, not both\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * If we forked a child, wait for it to exit. Cannot use waitpid()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * as all the delicious data would be reaped as part of the wait
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (tid && forking) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) int sig_received;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) sigwait(&sigset, &sig_received);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (tid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) cmd_type, &tid, sizeof(__u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) PRINTF("Sent pid/tgid, retval %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) fprintf(stderr, "error sending tid/tgid cmd\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (containerset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) cfd = open(containerpath, O_RDONLY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (cfd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) perror("error opening container file");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) rc = send_cmd(nl_sd, id, mypid, CGROUPSTATS_CMD_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) CGROUPSTATS_CMD_ATTR_FD, &cfd, sizeof(__u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (rc < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) perror("error sending cgroupstats command");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (!maskset && !tid && !containerset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) usage();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) rep_len = recv(nl_sd, &msg, sizeof(msg), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) PRINTF("received %d bytes\n", rep_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (rep_len < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) fprintf(stderr, "nonfatal reply error: errno %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) errno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (msg.n.nlmsg_type == NLMSG_ERROR ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) !NLMSG_OK((&msg.n), rep_len)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) struct nlmsgerr *err = NLMSG_DATA(&msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) fprintf(stderr, "fatal reply error, errno %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) err->error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) PRINTF("nlmsghdr size=%zu, nlmsg_len=%d, rep_len=%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) sizeof(struct nlmsghdr), msg.n.nlmsg_len, rep_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) rep_len = GENLMSG_PAYLOAD(&msg.n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) na = (struct nlattr *) GENLMSG_DATA(&msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) while (len < rep_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) len += NLA_ALIGN(na->nla_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) switch (na->nla_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) case TASKSTATS_TYPE_AGGR_TGID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) /* Fall through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) case TASKSTATS_TYPE_AGGR_PID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) aggr_len = NLA_PAYLOAD(na->nla_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) len2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) /* For nested attributes, na follows */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) na = (struct nlattr *) NLA_DATA(na);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) while (len2 < aggr_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) switch (na->nla_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) case TASKSTATS_TYPE_PID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) rtid = *(int *) NLA_DATA(na);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (print_delays)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) printf("PID\t%d\n", rtid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) case TASKSTATS_TYPE_TGID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) rtid = *(int *) NLA_DATA(na);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (print_delays)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) printf("TGID\t%d\n", rtid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) case TASKSTATS_TYPE_STATS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (print_delays)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) print_delayacct((struct taskstats *) NLA_DATA(na));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) if (print_io_accounting)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) print_ioacct((struct taskstats *) NLA_DATA(na));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (print_task_context_switch_counts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) task_context_switch_counts((struct taskstats *) NLA_DATA(na));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (fd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (write(fd, NLA_DATA(na), na->nla_len) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) err(1,"write error\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (!loop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) case TASKSTATS_TYPE_NULL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) fprintf(stderr, "Unknown nested"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) " nla_type %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) na->nla_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) len2 += NLA_ALIGN(na->nla_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) na = (struct nlattr *)((char *)na +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) NLA_ALIGN(na->nla_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) case CGROUPSTATS_TYPE_CGROUP_STATS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) print_cgroupstats(NLA_DATA(na));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) fprintf(stderr, "Unknown nla_type %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) na->nla_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) case TASKSTATS_TYPE_NULL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) na = (struct nlattr *) (GENLMSG_DATA(&msg) + len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) } while (loop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (maskset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) &cpumask, strlen(cpumask) + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) printf("Sent deregister mask, retval %d\n", rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) err(rc, "error sending deregister cpumask\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) close(nl_sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if (fd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (cfd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) close(cfd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }