Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }