Make-initrd development discussion
 help / color / mirror / Atom feed
* [make-initrd] [PATCH v1 00/11] Add accounting feature
@ 2023-06-15 17:59 Alexey Gladkov
  2023-06-15 17:59 ` [make-initrd] [PATCH v1 01/11] feature/procacct: New feature to debug initramfs Alexey Gladkov
                   ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
From: Alexey Gladkov @ 2023-06-15 17:59 UTC (permalink / raw)
  To: make-initrd

Привет!

Я написал фичу для отладки initramfs. Фича добавляет в бэкграунде процесс
аккаунтинга, который запускается на самых ранних этапах загрузки и собирает
данные о процессах. Перед запуском системного init формируется отчёт по
интересующим критериям.

Фича предназначена для отладки в тестах. Я хочу поразбираться, кто тратит больше
всего времени или cpu/memory. А то сейчас очень профилировать очень сложно.

Получилось сложнее, чем обычный acct(2), потому что я хотел получать не только
comm процесса т.к. у шелльных скриптов это bash. Хотелось максимально поймать
полный cmdline выполняемой программы.

Alexey Gladkov (11):
  feature/procacct: New feature to debug initramfs
  feature/procacct: Use epoll
  feature/procacct: Use default rcvbufsz
  feature/procacct: Track more values
  feature/procacct: Use msgtemplate instead of custom struct
  feature/procacct: Use nonblocking per-call
  feature/procacct: Add bpf helper
  feature/procacct: Add accounting report
  feature/procacct: Wait until procacct is initialized
  feature/procacct: Make procacct optional
  feature/procacct: Add to testing

 Makefile.in                                   |  10 +
 configure.ac                                  |  36 +
 data/etc/rc.d/rc.sysexec                      |  12 +
 data/etc/rc.d/rc.sysinit                      |  26 +-
 features/debug-procacct/README.md             |   3 +
 features/debug-procacct/config.mk             |   1 +
 .../debug-procacct/data/bin/procacct-report   | 117 ++++
 .../data/etc/initrd/cmdline.d/procacct        |   1 +
 features/debug-procacct/rules.mk              |   1 +
 features/debug-procacct/src/Makefile.mk       |  16 +
 features/debug-procacct/src/procacct-bpf.c    |  57 ++
 features/debug-procacct/src/procacct.c        | 634 ++++++++++++++++++
 features/debug-procacct/src/procacct.h        |  13 +
 testing/packages-altlinux                     |   3 +-
 testing/test-root-btrfs-subvol.cfg            |   2 +-
 testing/test-root-efi-partition.cfg           |   2 +-
 testing/test-root-efi-reqpartition.cfg        |   2 +-
 testing/test-root-luks+crypttab+noparam.cfg   |   2 +-
 testing/test-root-luks+lukskey-noparam.cfg    |   2 +-
 testing/test-root-luks+lukskey-plain.cfg      |   2 +-
 testing/test-root-luks+lukskey-raw.cfg        |   2 +-
 testing/test-root-luks-over-lvm.cfg           |   2 +-
 testing/test-root-luks-over-raid1.cfg         |   2 +-
 testing/test-root-luks.cfg                    |   2 +-
 testing/test-root-lvm+luks.cfg                |   2 +-
 testing/test-root-lvm.cfg                     |   2 +-
 testing/test-root-partition+usr.cfg           |   2 +-
 testing/test-root-partition.cfg               |   2 +-
 testing/test-root-pipeline.cfg                |   2 +-
 testing/test-root-raid1+raid5.cfg             |   2 +-
 testing/test-root-raid1-degraded.cfg          |   2 +-
 testing/test-root-raid1.cfg                   |   2 +-
 testing/test-root-raid5.cfg                   |   2 +-
 testing/test-root-sshfs-network-dhcp.cfg      |   2 +-
 testing/test-root-sshfs-network-static1.cfg   |   2 +-
 testing/test-root-zfs-partition.cfg           |   2 +-
 testing/testing-altlinux-local                |   9 +
 testing/testing-ks-initrd.cfg                 |   1 +
 38 files changed, 955 insertions(+), 29 deletions(-)
 create mode 100644 features/debug-procacct/README.md
 create mode 100644 features/debug-procacct/config.mk
 create mode 100755 features/debug-procacct/data/bin/procacct-report
 create mode 100644 features/debug-procacct/data/etc/initrd/cmdline.d/procacct
 create mode 100644 features/debug-procacct/rules.mk
 create mode 100644 features/debug-procacct/src/Makefile.mk
 create mode 100644 features/debug-procacct/src/procacct-bpf.c
 create mode 100644 features/debug-procacct/src/procacct.c
 create mode 100644 features/debug-procacct/src/procacct.h

-- 
2.33.8



^ permalink raw reply	[flat|nested] 12+ messages in thread

* [make-initrd] [PATCH v1 01/11] feature/procacct: New feature to debug initramfs
  2023-06-15 17:59 [make-initrd] [PATCH v1 00/11] Add accounting feature Alexey Gladkov
@ 2023-06-15 17:59 ` Alexey Gladkov
  2023-06-15 17:59 ` [make-initrd] [PATCH v1 02/11] feature/procacct: Use epoll Alexey Gladkov
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Alexey Gladkov @ 2023-06-15 17:59 UTC (permalink / raw)
  To: make-initrd

Based on an example of accounting from the linux kernel sources
tools/accounting/procacct.c

Signed-off-by: Alexey Gladkov <gladkov.alexey@gmail.com>
---
 features/debug-procacct/README.md       |   3 +
 features/debug-procacct/config.mk       |   1 +
 features/debug-procacct/rules.mk        |   1 +
 features/debug-procacct/src/Makefile.mk |   6 +
 features/debug-procacct/src/procacct.c  | 395 ++++++++++++++++++++++++
 5 files changed, 406 insertions(+)
 create mode 100644 features/debug-procacct/README.md
 create mode 100644 features/debug-procacct/config.mk
 create mode 100644 features/debug-procacct/rules.mk
 create mode 100644 features/debug-procacct/src/Makefile.mk
 create mode 100644 features/debug-procacct/src/procacct.c

diff --git a/features/debug-procacct/README.md b/features/debug-procacct/README.md
new file mode 100644
index 00000000..59e39a61
--- /dev/null
+++ b/features/debug-procacct/README.md
@@ -0,0 +1,3 @@
+# debug-procacct
+
+The feature is designed to debug the boot process inside the initramfs.
diff --git a/features/debug-procacct/config.mk b/features/debug-procacct/config.mk
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/features/debug-procacct/config.mk
@@ -0,0 +1 @@
+
diff --git a/features/debug-procacct/rules.mk b/features/debug-procacct/rules.mk
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/features/debug-procacct/rules.mk
@@ -0,0 +1 @@
+
diff --git a/features/debug-procacct/src/Makefile.mk b/features/debug-procacct/src/Makefile.mk
new file mode 100644
index 00000000..ea02bf91
--- /dev/null
+++ b/features/debug-procacct/src/Makefile.mk
@@ -0,0 +1,6 @@
+procacct_DEST = $(dest_data_bindir)/procacct
+procacct_SRCS = $(FEATURESDIR)/debug-procacct/src/procacct.c
+procacct_CFLAGS = -D_GNU_SOURCE -Idatasrc/libinitramfs
+procacct_LIBS = -L$(dest_data_libdir) -linitramfs
+
+PROGS += procacct
diff --git a/features/debug-procacct/src/procacct.c b/features/debug-procacct/src/procacct.c
new file mode 100644
index 00000000..9302edb0
--- /dev/null
+++ b/features/debug-procacct/src/procacct.c
@@ -0,0 +1,395 @@
+// SPDX-License-Identifier: GPL-2.0
+/* procacct.c
+ *
+ * Demonstrator of fetching resource data on task exit, as a way
+ * to accumulate accurate program resource usage statistics, without
+ * prior identification of the programs. For that, the fields for
+ * device and inode of the program executable binary file are also
+ * extracted in addition to the command string.
+ *
+ * The TGID together with the PID and the AGROUP flag allow
+ * identification of threads in a process and single-threaded processes.
+ * The ac_tgetime field gives proper whole-process walltime.
+ *
+ * Written (changed) by Thomas Orgis, University of Hamburg in 2022
+ *
+ * This is a cheap derivation (inheriting the style) of 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
+ */
+#include <linux/genetlink.h>
+#include <linux/acct.h>
+#include <linux/taskstats.h>
+#include <linux/kdev_t.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <errno.h>
+#include <limits.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <search.h>
+
+#include "rd/logging.h"
+
+/* 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 64
+
+/*
+ * 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)
+
+static pid_t current_pid;
+static int rcvbufsz;
+static char name[100];
+
+struct msgtemplate {
+	struct nlmsghdr n;
+	struct genlmsghdr g;
+	char buf[MAX_MSG_SIZE];
+};
+
+static void *proc_root = NULL;
+
+struct proc_cmdline {
+	pid_t pid;
+	char *cmdline;
+};
+
+static void usage(void)                                                       __attribute__((noreturn));
+static int proc_compare(const void *a, const void *b)                         __attribute__((nonnull(1, 2)));
+static int create_nl_socket(int protocol);
+static ssize_t send_cmd(int fd, uint16_t nlmsg_type, uint8_t genl_cmd,
+                        uint16_t nla_type, void *nla_data, uint16_t nla_len);
+static uint16_t get_family_id(int fd);
+static void print_procacct(int fd, struct taskstats *t)                       __attribute__((nonnull(2)));
+static void handle_aggr(struct nlattr *na, int fd)                            __attribute__((nonnull(1)));
+
+int proc_compare(const void *a, const void *b)
+{
+	pid_t pid_a = ((struct proc_cmdline *)a)->pid;
+	pid_t pid_b = ((struct proc_cmdline *)b)->pid;
+
+	if (pid_a < pid_b)
+		return -1;
+	if (pid_a > pid_b)
+		return 1;
+	return 0;
+}
+
+void usage(void)
+{
+	fprintf(stderr, "procacct [-o logfile] [-r bufsize] [-m cpumask]\n");
+	exit(1);
+}
+
+/*
+ * Create a raw netlink socket and bind
+ */
+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) {
+			rd_err("unable to set socket rcv buf size to %d", rcvbufsz);
+			goto error;
+		}
+	}
+
+	memset(&local, 0, sizeof(local));
+	local.nl_family = AF_NETLINK;
+
+	if (bind(fd, (struct sockaddr *) &local, sizeof(local)) < 0) {
+		rd_err("unable bind to socket");
+		goto error;
+	}
+
+	return fd;
+error:
+	close(fd);
+	return -1;
+}
+
+
+ssize_t send_cmd(int fd, uint16_t nlmsg_type, uint8_t genl_cmd, uint16_t nla_type, void *nla_data, uint16_t nla_len)
+{
+	struct nlattr *na;
+	struct sockaddr_nl nladdr;
+
+	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 = (uint32_t) current_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);
+
+	char *buf = (char *) &msg;
+	ssize_t buflen = msg.n.nlmsg_len;
+
+	memset(&nladdr, 0, sizeof(nladdr));
+	nladdr.nl_family = AF_NETLINK;
+
+	ssize_t ret;
+
+	while ((ret = sendto(fd, buf, (size_t) buflen, 0, (struct sockaddr *) &nladdr, sizeof(nladdr))) < buflen) {
+		if (ret > 0) {
+			buf += ret;
+			buflen -= ret;
+		} else if (errno != EINTR && errno != EAGAIN) {
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+
+/*
+ * Probe the controller in genetlink to find the family id
+ * for the TASKSTATS family
+ */
+uint16_t get_family_id(int fd)
+{
+	struct {
+		struct nlmsghdr n;
+		struct genlmsghdr g;
+		char buf[256];
+	} ans;
+
+	strcpy(name, TASKSTATS_GENL_NAME);
+
+	ssize_t ret = send_cmd(fd, GENL_ID_CTRL, CTRL_CMD_GETFAMILY,
+	                       CTRL_ATTR_FAMILY_NAME, name, strlen(TASKSTATS_GENL_NAME) + 1);
+	if (ret < 0)
+		return 0;
+
+	ret = recv(fd, &ans, sizeof(ans), 0);
+
+	if (ans.n.nlmsg_type == NLMSG_ERROR || (ret < 0) || !NLMSG_OK((&ans.n), ret))
+		return 0;
+
+	struct nlattr *na;
+
+	na = (struct nlattr *) GENLMSG_DATA(&ans);
+	na = (struct nlattr *) ((char *) na + NLA_ALIGN(na->nla_len));
+
+	uint16_t id = 0;
+
+	if (na->nla_type == CTRL_ATTR_FAMILY_ID)
+		id = *(uint16_t *) NLA_DATA(na);
+
+	return id;
+}
+
+void print_procacct(int fd, struct taskstats *t)
+{
+	struct proc_cmdline key = { .pid = (pid_t) t->ac_pid };
+	struct proc_cmdline *proc = tfind(&key, proc_root, proc_compare);
+
+	dprintf(fd,
+	        "%c\t%u\t%u\t%llu\t%llu\t%llu\t%llu\t %llu\t[%s]\t%s\n",
+	        // First letter: T is a mere thread, G the last in a group, U  unknown.
+	        (t->version >= 12 ? (t->ac_flag & AGROUP ? 'P' : 'T') : '?'),
+	        (t->ac_pid),                         // pid
+	        (t->version >= 12 ? t->ac_tgid : 0), // tgid
+	        (t->ac_btime64),                     // btime
+	        (t->ac_etime),                       // wall
+	        (t->ac_utime + t->ac_stime),         // cputime
+	        (t->hiwater_vm),                     // vmusage
+	        (t->hiwater_rss),                    // rssusage
+	        (t->ac_comm),                        // comm
+	        (proc ? proc->cmdline : "")          // cmdline
+	       );
+}
+
+void handle_aggr(struct nlattr *na, int fd)
+{
+	int nla_type = na->nla_type;
+	int aggr_len = NLA_PAYLOAD(na->nla_len);
+	int len2 = 0;
+
+	na = (struct nlattr *) NLA_DATA(na);
+	while (len2 < aggr_len) {
+		switch (na->nla_type) {
+			case TASKSTATS_TYPE_PID:
+			case TASKSTATS_TYPE_TGID:
+				break;
+			case TASKSTATS_TYPE_STATS:
+				if (nla_type == TASKSTATS_TYPE_AGGR_PID)
+					print_procacct(fd, (struct taskstats *) NLA_DATA(na));
+				break;
+			case TASKSTATS_TYPE_NULL:
+				break;
+			default:
+				rd_err("unknown nested nla_type %d", na->nla_type);
+				break;
+		}
+		len2 += NLA_ALIGN(na->nla_len);
+		na = (struct nlattr *)((char *) na + NLA_ALIGN(na->nla_len));
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	ssize_t ret;
+	uint16_t id;
+
+	char cpumask[100 + 6 * MAX_CPUS];
+	uint16_t cpumask_len;
+
+	int fd_nlink = -1;
+	int fd_out = 1;
+	int write_file = 0;
+	int maskset = 0;
+	char *logfile = NULL;
+
+	while (1) {
+		int c = getopt(argc, argv, "m:o:r:");
+		if (c < 0)
+			break;
+
+		switch (c) {
+			case 'o':
+				logfile = strdup(optarg);
+				write_file = 1;
+				break;
+			case 'r':
+				rcvbufsz = atoi(optarg);
+				if (rcvbufsz < 0)
+					rd_fatal("invalid rcv buf size");
+				break;
+			case 'm':
+				strlcpy(cpumask, optarg, sizeof(cpumask));
+				maskset = 1;
+				break;
+			default:
+				usage();
+		}
+	}
+	if (!maskset) {
+		long np = sysconf(_SC_NPROCESSORS_ONLN);
+		if (np > 1)
+			snprintf(cpumask, sizeof(cpumask), "0-%ld", np - 1);
+		else
+			snprintf(cpumask, sizeof(cpumask), "1");
+	}
+
+	if ((strlen(cpumask) + 1) > USHRT_MAX)
+		rd_fatal("cpumask too long");
+
+	cpumask_len = (uint16_t) strlen(cpumask) + 1;
+
+	if (write_file) {
+		fd_out = open(logfile, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, 0644);
+		if (fd_out < 0)
+			rd_fatal("cannot open output file: %s: %m", logfile);
+	}
+
+	fd_nlink = create_nl_socket(NETLINK_GENERIC);
+	if (fd_nlink < 0)
+		rd_fatal("error creating Netlink socket: %m");
+
+	current_pid = getpid();
+
+	id = get_family_id(fd_nlink);
+	if (!id) {
+		rd_err("error getting family id, errno=%d", errno);
+		goto err;
+	}
+
+	ret = send_cmd(fd_nlink, id, TASKSTATS_CMD_GET,
+	               TASKSTATS_CMD_ATTR_REGISTER_CPUMASK, &cpumask, cpumask_len);
+	if (ret < 0) {
+		rd_err("error sending register cpumask");
+		goto err;
+	}
+
+	while (1) {
+		struct msgtemplate msg;
+		struct nlattr *na;
+
+		ret = recv(fd_nlink, &msg, sizeof(msg), 0);
+		if (ret < 0) {
+			rd_err("nonfatal reply error: errno=%d", errno);
+			continue;
+		}
+
+		if (msg.n.nlmsg_type == NLMSG_ERROR || !NLMSG_OK((&msg.n), ret)) {
+			struct nlmsgerr *err = NLMSG_DATA(&msg);
+			rd_fatal("fatal reply error, errno=%d", err->error);
+		}
+
+		ret = GENLMSG_PAYLOAD(&msg.n);
+		na = (struct nlattr *) GENLMSG_DATA(&msg);
+
+		ssize_t len = 0;
+
+		while (len < ret) {
+			switch (na->nla_type) {
+				case TASKSTATS_TYPE_NULL:
+					break;
+				case TASKSTATS_TYPE_AGGR_PID:
+				case TASKSTATS_TYPE_AGGR_TGID:
+					/* For nested attributes, na follows */
+					handle_aggr(na, fd_out);
+					break;
+				default:
+					rd_err("unexpected nla_type %d", na->nla_type);
+			}
+
+			len += NLA_ALIGN(na->nla_len);
+			na = (struct nlattr *) (GENLMSG_DATA(&msg) + len);
+		}
+	}
+
+	ret = send_cmd(fd_nlink, id, TASKSTATS_CMD_GET,
+	               TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK, &cpumask, cpumask_len);
+	if (ret < 0)
+		rd_fatal("error sending deregister cpumask");
+err:
+	close(fd_nlink);
+
+	if (fd_out)
+		close(fd_out);
+
+	return 0;
+}
-- 
2.33.8



^ permalink raw reply	[flat|nested] 12+ messages in thread

* [make-initrd] [PATCH v1 02/11] feature/procacct: Use epoll
  2023-06-15 17:59 [make-initrd] [PATCH v1 00/11] Add accounting feature Alexey Gladkov
  2023-06-15 17:59 ` [make-initrd] [PATCH v1 01/11] feature/procacct: New feature to debug initramfs Alexey Gladkov
@ 2023-06-15 17:59 ` Alexey Gladkov
  2023-06-15 17:59 ` [make-initrd] [PATCH v1 03/11] feature/procacct: Use default rcvbufsz Alexey Gladkov
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Alexey Gladkov @ 2023-06-15 17:59 UTC (permalink / raw)
  To: make-initrd

This is preparation for adding more event sources.

Signed-off-by: Alexey Gladkov <gladkov.alexey@gmail.com>
---
 features/debug-procacct/src/procacct.c | 288 +++++++++++++++++--------
 1 file changed, 200 insertions(+), 88 deletions(-)

diff --git a/features/debug-procacct/src/procacct.c b/features/debug-procacct/src/procacct.c
index 9302edb0..cfb4de1f 100644
--- a/features/debug-procacct/src/procacct.c
+++ b/features/debug-procacct/src/procacct.c
@@ -31,6 +31,7 @@
 #include <sys/stat.h>
 #include <sys/socket.h>
 #include <sys/wait.h>
+#include <sys/epoll.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -43,6 +44,7 @@
 #include <search.h>
 
 #include "rd/logging.h"
+#include "rd/memory.h"
 
 /* Maximum size of response requested or message sent */
 #define MAX_MSG_SIZE 1024
@@ -63,6 +65,7 @@
 static pid_t current_pid;
 static int rcvbufsz;
 static char name[100];
+static int fd_out = 1;
 
 struct msgtemplate {
 	struct nlmsghdr n;
@@ -77,14 +80,44 @@ struct proc_cmdline {
 	char *cmdline;
 };
 
+struct ctx_netlink {
+	uint16_t cpuid;
+	uint16_t cpumask_len;
+	char cpumask[100 + 6 * MAX_CPUS];
+};
+
+enum {
+	FD_NETLINK,
+	FD_MAX,
+};
+
+#define EV_MAX (FD_MAX * 32)
+
+struct fd_handler;
+typedef int (*fdhandler_t)(struct fd_handler *);
+
+struct fd_handler {
+	int fd;
+	fdhandler_t fd_prepare;
+	fdhandler_t fd_handler;
+	fdhandler_t fd_finish;
+	void *data;
+};
+
+static struct fd_handler fd_handler_list[FD_MAX];
+
 static void usage(void)                                                       __attribute__((noreturn));
 static int proc_compare(const void *a, const void *b)                         __attribute__((nonnull(1, 2)));
-static int create_nl_socket(int protocol);
+static int process_netlink_events(struct fd_handler *el);
+static int prepare_netlink(struct fd_handler *el);
+static int finish_netlink(struct fd_handler *el);
+static void setup_netlink_fd(struct fd_handler *el);
 static ssize_t send_cmd(int fd, uint16_t nlmsg_type, uint8_t genl_cmd,
                         uint16_t nla_type, void *nla_data, uint16_t nla_len);
 static uint16_t get_family_id(int fd);
 static void print_procacct(int fd, struct taskstats *t)                       __attribute__((nonnull(2)));
 static void handle_aggr(struct nlattr *na, int fd)                            __attribute__((nonnull(1)));
+static int setup_epoll_fd(struct fd_handler list[FD_MAX]);
 
 int proc_compare(const void *a, const void *b)
 {
@@ -100,44 +133,35 @@ int proc_compare(const void *a, const void *b)
 
 void usage(void)
 {
-	fprintf(stderr, "procacct [-o logfile] [-r bufsize] [-m cpumask]\n");
+	fprintf(stderr, "procacct [-o logfile] [-r bufsize]\n");
 	exit(1);
 }
 
 /*
  * Create a raw netlink socket and bind
  */
-int create_nl_socket(int protocol)
+void setup_netlink_fd(struct fd_handler *el)
 {
-	int fd;
 	struct sockaddr_nl local;
 
-	fd = socket(AF_NETLINK, SOCK_RAW, protocol);
-	if (fd < 0)
-		return -1;
+	el->fd = socket(AF_NETLINK, SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC, NETLINK_GENERIC);
+	if (el->fd < 0)
+		rd_fatal("error creating Netlink socket: %m");
 
-	if (rcvbufsz) {
-		if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbufsz, sizeof(rcvbufsz)) < 0) {
-			rd_err("unable to set socket rcv buf size to %d", rcvbufsz);
-			goto error;
-		}
-	}
+	if (rcvbufsz && setsockopt(el->fd, SOL_SOCKET, SO_RCVBUF, &rcvbufsz, sizeof(rcvbufsz)) < 0)
+		rd_fatal("unable to set socket rcv buf size to %d", rcvbufsz);
 
 	memset(&local, 0, sizeof(local));
 	local.nl_family = AF_NETLINK;
 
-	if (bind(fd, (struct sockaddr *) &local, sizeof(local)) < 0) {
-		rd_err("unable bind to socket");
-		goto error;
-	}
+	if (bind(el->fd, (struct sockaddr *) &local, sizeof(local)) < 0)
+		rd_fatal("unable bind to socket");
 
-	return fd;
-error:
-	close(fd);
-	return -1;
+	el->fd_handler = process_netlink_events;
+	el->fd_prepare = prepare_netlink;
+	el->fd_finish  = finish_netlink;
 }
 
-
 ssize_t send_cmd(int fd, uint16_t nlmsg_type, uint8_t genl_cmd, uint16_t nla_type, void *nla_data, uint16_t nla_len)
 {
 	struct nlattr *na;
@@ -268,89 +292,80 @@ void handle_aggr(struct nlattr *na, int fd)
 	}
 }
 
-int main(int argc, char *argv[])
+int prepare_netlink(struct fd_handler *el)
 {
+	struct ctx_netlink *ctx;
 	ssize_t ret;
-	uint16_t id;
 
-	char cpumask[100 + 6 * MAX_CPUS];
-	uint16_t cpumask_len;
+	ctx = rd_calloc_or_die(1, sizeof(*ctx));
 
-	int fd_nlink = -1;
-	int fd_out = 1;
-	int write_file = 0;
-	int maskset = 0;
-	char *logfile = NULL;
+	long np = sysconf(_SC_NPROCESSORS_ONLN);
+	if (np > 1)
+		snprintf(ctx->cpumask, sizeof(ctx->cpumask), "0-%ld", np - 1);
+	else
+		snprintf(ctx->cpumask, sizeof(ctx->cpumask), "1");
 
-	while (1) {
-		int c = getopt(argc, argv, "m:o:r:");
-		if (c < 0)
-			break;
-
-		switch (c) {
-			case 'o':
-				logfile = strdup(optarg);
-				write_file = 1;
-				break;
-			case 'r':
-				rcvbufsz = atoi(optarg);
-				if (rcvbufsz < 0)
-					rd_fatal("invalid rcv buf size");
-				break;
-			case 'm':
-				strlcpy(cpumask, optarg, sizeof(cpumask));
-				maskset = 1;
-				break;
-			default:
-				usage();
-		}
-	}
-	if (!maskset) {
-		long np = sysconf(_SC_NPROCESSORS_ONLN);
-		if (np > 1)
-			snprintf(cpumask, sizeof(cpumask), "0-%ld", np - 1);
-		else
-			snprintf(cpumask, sizeof(cpumask), "1");
+	if ((strlen(ctx->cpumask) + 1) > USHRT_MAX) {
+		rd_err("cpumask too long");
+		free(ctx);
+		return -1;
 	}
 
-	if ((strlen(cpumask) + 1) > USHRT_MAX)
-		rd_fatal("cpumask too long");
+	ctx->cpumask_len = (uint16_t) strlen(ctx->cpumask) + 1;
 
-	cpumask_len = (uint16_t) strlen(cpumask) + 1;
+	ctx->cpuid = get_family_id(el->fd);
+	if (!ctx->cpuid) {
+		rd_err("error getting family id, errno=%d", errno);
+		free(ctx);
+		return -1;
+	}
 
-	if (write_file) {
-		fd_out = open(logfile, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, 0644);
-		if (fd_out < 0)
-			rd_fatal("cannot open output file: %s: %m", logfile);
+	ret = send_cmd(el->fd, ctx->cpuid, TASKSTATS_CMD_GET,
+	               TASKSTATS_CMD_ATTR_REGISTER_CPUMASK,
+		       &ctx->cpumask, ctx->cpumask_len);
+	if (ret < 0) {
+		rd_err("error sending register cpumask");
+		free(ctx);
+		return -1;
 	}
 
-	fd_nlink = create_nl_socket(NETLINK_GENERIC);
-	if (fd_nlink < 0)
-		rd_fatal("error creating Netlink socket: %m");
+	el->data = ctx;
 
-	current_pid = getpid();
+	return 0;
+}
 
-	id = get_family_id(fd_nlink);
-	if (!id) {
-		rd_err("error getting family id, errno=%d", errno);
-		goto err;
-	}
+int finish_netlink(struct fd_handler *el)
+{
+	struct ctx_netlink *ctx = el->data;
+	ssize_t ret;
 
-	ret = send_cmd(fd_nlink, id, TASKSTATS_CMD_GET,
-	               TASKSTATS_CMD_ATTR_REGISTER_CPUMASK, &cpumask, cpumask_len);
+	ret = send_cmd(el->fd, ctx->cpuid, TASKSTATS_CMD_GET,
+	               TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK,
+		       &ctx->cpumask, ctx->cpumask_len);
 	if (ret < 0) {
-		rd_err("error sending register cpumask");
-		goto err;
+		rd_err("error sending deregister cpumask");
+		return -1;
 	}
+	free(ctx);
+	return 0;
+}
+
+int process_netlink_events(struct fd_handler *el)
+{
+	ssize_t ret;
 
 	while (1) {
 		struct msgtemplate msg;
 		struct nlattr *na;
 
-		ret = recv(fd_nlink, &msg, sizeof(msg), 0);
+		errno = 0;
+		ret = recv(el->fd, &msg, sizeof(msg), 0);
 		if (ret < 0) {
-			rd_err("nonfatal reply error: errno=%d", errno);
-			continue;
+			if (errno == EAGAIN || errno == EWOULDBLOCK)
+				return 0;
+			if (errno == EINTR)
+				continue;
+			rd_fatal("nonfatal reply error: %m");
 		}
 
 		if (msg.n.nlmsg_type == NLMSG_ERROR || !NLMSG_OK((&msg.n), ret)) {
@@ -381,12 +396,109 @@ int main(int argc, char *argv[])
 		}
 	}
 
-	ret = send_cmd(fd_nlink, id, TASKSTATS_CMD_GET,
-	               TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK, &cpumask, cpumask_len);
-	if (ret < 0)
-		rd_fatal("error sending deregister cpumask");
+	return 0;
+}
+
+int setup_epoll_fd(struct fd_handler list[FD_MAX])
+{
+	int epollfd;
+	struct epoll_event ev = { .events = EPOLLIN };
+
+	if ((epollfd = epoll_create1(EPOLL_CLOEXEC)) < 0)
+		rd_fatal("epoll_create1: %m");
+
+	for (int i = 0; i < FD_MAX; i++) {
+		ev.data.ptr = &list[i];
+
+		if (epoll_ctl(epollfd, EPOLL_CTL_ADD, list[i].fd, &ev) < 0)
+			rd_fatal("epoll_ctl: %m");
+	}
+
+	return epollfd;
+}
+
+int main(int argc, char *argv[])
+{
+	int fd_epoll = -1;
+	int write_file = 0;
+	char *logfile = NULL;
+
+	while (1) {
+		int c = getopt(argc, argv, "o:r:");
+		if (c < 0)
+			break;
+
+		switch (c) {
+			case 'o':
+				logfile = strdup(optarg);
+				write_file = 1;
+				break;
+			case 'r':
+				rcvbufsz = atoi(optarg);
+				if (rcvbufsz < 0)
+					rd_fatal("invalid rcv buf size");
+				break;
+			default:
+				usage();
+		}
+	}
+
+	if (write_file) {
+		fd_out = open(logfile, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, 0644);
+		if (fd_out < 0)
+			rd_fatal("cannot open output file: %s: %m", logfile);
+	}
+
+	current_pid = getpid();
+
+	setup_netlink_fd(&fd_handler_list[FD_NETLINK]);
+	fd_epoll = setup_epoll_fd(fd_handler_list);
+
+	for (int i = 0; i < FD_MAX; i++) {
+		if (fd_handler_list[i].fd < 0 || !fd_handler_list[i].fd_prepare)
+			continue;
+		if (fd_handler_list[i].fd_prepare(&fd_handler_list[i]) < 0)
+			rd_fatal("unable to prepare file descriptor");
+	}
+
+	while (1) {
+		struct epoll_event ev[EV_MAX];
+		int fdcount;
+
+		errno = 0;
+		fdcount = epoll_wait(fd_epoll, ev, EV_MAX, -1);
+
+		if (fdcount < 0) {
+			if (errno == EINTR)
+				continue;
+			rd_fatal("epoll_wait: %m");
+		}
+
+		for (int i = 0; i < fdcount; i++) {
+			if (!(ev[i].events & EPOLLIN))
+				continue;
+
+			struct fd_handler *fde = ev[i].data.ptr;
+
+			if (fde->fd_handler(fde) != 0)
+				goto err;
+		}
+	}
+
 err:
-	close(fd_nlink);
+	for (int i = 0; i < FD_MAX; i++) {
+		if (fd_handler_list[i].fd < 0)
+			continue;
+
+		if (epoll_ctl(fd_epoll, EPOLL_CTL_DEL, fd_handler_list[i].fd, NULL) < 0)
+			rd_err("epoll_ctl: %m");
+
+		if (fd_handler_list[i].fd_finish)
+			fd_handler_list[i].fd_finish(&fd_handler_list[i]);
+
+		close(fd_handler_list[i].fd);
+	}
+	close(fd_epoll);
 
 	if (fd_out)
 		close(fd_out);
-- 
2.33.8



^ permalink raw reply	[flat|nested] 12+ messages in thread

* [make-initrd] [PATCH v1 03/11] feature/procacct: Use default rcvbufsz
  2023-06-15 17:59 [make-initrd] [PATCH v1 00/11] Add accounting feature Alexey Gladkov
  2023-06-15 17:59 ` [make-initrd] [PATCH v1 01/11] feature/procacct: New feature to debug initramfs Alexey Gladkov
  2023-06-15 17:59 ` [make-initrd] [PATCH v1 02/11] feature/procacct: Use epoll Alexey Gladkov
@ 2023-06-15 17:59 ` Alexey Gladkov
  2023-06-15 17:59 ` [make-initrd] [PATCH v1 04/11] feature/procacct: Track more values Alexey Gladkov
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Alexey Gladkov @ 2023-06-15 17:59 UTC (permalink / raw)
  To: make-initrd

Signed-off-by: Alexey Gladkov <gladkov.alexey@gmail.com>
---
 features/debug-procacct/src/procacct.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/features/debug-procacct/src/procacct.c b/features/debug-procacct/src/procacct.c
index cfb4de1f..1e594ae4 100644
--- a/features/debug-procacct/src/procacct.c
+++ b/features/debug-procacct/src/procacct.c
@@ -63,7 +63,7 @@
 #define NLA_PAYLOAD(len)	(len - NLA_HDRLEN)
 
 static pid_t current_pid;
-static int rcvbufsz;
+static int rcvbufsz = MAX_MSG_SIZE * 32;
 static char name[100];
 static int fd_out = 1;
 
-- 
2.33.8



^ permalink raw reply	[flat|nested] 12+ messages in thread

* [make-initrd] [PATCH v1 04/11] feature/procacct: Track more values
  2023-06-15 17:59 [make-initrd] [PATCH v1 00/11] Add accounting feature Alexey Gladkov
                   ` (2 preceding siblings ...)
  2023-06-15 17:59 ` [make-initrd] [PATCH v1 03/11] feature/procacct: Use default rcvbufsz Alexey Gladkov
@ 2023-06-15 17:59 ` Alexey Gladkov
  2023-06-15 17:59 ` [make-initrd] [PATCH v1 05/11] feature/procacct: Use msgtemplate instead of custom struct Alexey Gladkov
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Alexey Gladkov @ 2023-06-15 17:59 UTC (permalink / raw)
  To: make-initrd

Signed-off-by: Alexey Gladkov <gladkov.alexey@gmail.com>
---
 features/debug-procacct/src/procacct.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/features/debug-procacct/src/procacct.c b/features/debug-procacct/src/procacct.c
index 1e594ae4..522a82f1 100644
--- a/features/debug-procacct/src/procacct.c
+++ b/features/debug-procacct/src/procacct.c
@@ -250,16 +250,21 @@ void print_procacct(int fd, struct taskstats *t)
 	struct proc_cmdline *proc = tfind(&key, proc_root, proc_compare);
 
 	dprintf(fd,
-	        "%c\t%u\t%u\t%llu\t%llu\t%llu\t%llu\t %llu\t[%s]\t%s\n",
+	        "%c\t%u\t%u\t%u\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t[%s]\t%s\n",
 	        // First letter: T is a mere thread, G the last in a group, U  unknown.
 	        (t->version >= 12 ? (t->ac_flag & AGROUP ? 'P' : 'T') : '?'),
 	        (t->ac_pid),                         // pid
 	        (t->version >= 12 ? t->ac_tgid : 0), // tgid
+	        (t->ac_ppid),                        // ppid
 	        (t->ac_btime64),                     // btime
 	        (t->ac_etime),                       // wall
 	        (t->ac_utime + t->ac_stime),         // cputime
 	        (t->hiwater_vm),                     // vmusage
 	        (t->hiwater_rss),                    // rssusage
+	        (t->read_char),                      // bytes read
+	        (t->write_char),                     // bytes write
+	        (t->read_bytes),                     // bytes of read I/O
+	        (t->write_bytes),                    // bytes of write I/O
 	        (t->ac_comm),                        // comm
 	        (proc ? proc->cmdline : "")          // cmdline
 	       );
-- 
2.33.8



^ permalink raw reply	[flat|nested] 12+ messages in thread

* [make-initrd] [PATCH v1 05/11] feature/procacct: Use msgtemplate instead of custom struct
  2023-06-15 17:59 [make-initrd] [PATCH v1 00/11] Add accounting feature Alexey Gladkov
                   ` (3 preceding siblings ...)
  2023-06-15 17:59 ` [make-initrd] [PATCH v1 04/11] feature/procacct: Track more values Alexey Gladkov
@ 2023-06-15 17:59 ` Alexey Gladkov
  2023-06-15 17:59 ` [make-initrd] [PATCH v1 06/11] feature/procacct: Use nonblocking per-call Alexey Gladkov
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Alexey Gladkov @ 2023-06-15 17:59 UTC (permalink / raw)
  To: make-initrd

Signed-off-by: Alexey Gladkov <gladkov.alexey@gmail.com>
---
 features/debug-procacct/src/procacct.c | 35 ++++++++++++--------------
 1 file changed, 16 insertions(+), 19 deletions(-)

diff --git a/features/debug-procacct/src/procacct.c b/features/debug-procacct/src/procacct.c
index 522a82f1..0ff9030f 100644
--- a/features/debug-procacct/src/procacct.c
+++ b/features/debug-procacct/src/procacct.c
@@ -47,7 +47,7 @@
 #include "rd/memory.h"
 
 /* Maximum size of response requested or message sent */
-#define MAX_MSG_SIZE 1024
+#define MAX_MSG_SIZE 2048
 
 /* Maximum number of cpus expected to be specified in a cpumask */
 #define MAX_CPUS 64
@@ -213,35 +213,32 @@ ssize_t send_cmd(int fd, uint16_t nlmsg_type, uint8_t genl_cmd, uint16_t nla_typ
  */
 uint16_t get_family_id(int fd)
 {
-	struct {
-		struct nlmsghdr n;
-		struct genlmsghdr g;
-		char buf[256];
-	} ans;
-
-	strcpy(name, TASKSTATS_GENL_NAME);
+	struct msgtemplate msg;
 
 	ssize_t ret = send_cmd(fd, GENL_ID_CTRL, CTRL_CMD_GETFAMILY,
-	                       CTRL_ATTR_FAMILY_NAME, name, strlen(TASKSTATS_GENL_NAME) + 1);
+	                       CTRL_ATTR_FAMILY_NAME,
+	                       (char *) TASKSTATS_GENL_NAME, sizeof(TASKSTATS_GENL_NAME));
 	if (ret < 0)
 		return 0;
 
-	ret = recv(fd, &ans, sizeof(ans), 0);
+	ret = recv(fd, &msg, sizeof(msg), 0);
+	if (ret < 0)
+		rd_fatal("receive NETLINK family: %m");
 
-	if (ans.n.nlmsg_type == NLMSG_ERROR || (ret < 0) || !NLMSG_OK((&ans.n), ret))
-		return 0;
+	if (msg.n.nlmsg_type == NLMSG_ERROR || !NLMSG_OK((&msg.n), ret)) {
+		struct nlmsgerr *err = NLMSG_DATA(&msg);
+		rd_fatal("receive NETLINK family: %s (errno=%d)", strerror(-err->error),  err->error);
+	}
 
 	struct nlattr *na;
 
-	na = (struct nlattr *) GENLMSG_DATA(&ans);
+	na = (struct nlattr *) GENLMSG_DATA(&msg);
 	na = (struct nlattr *) ((char *) na + NLA_ALIGN(na->nla_len));
 
-	uint16_t id = 0;
-
-	if (na->nla_type == CTRL_ATTR_FAMILY_ID)
-		id = *(uint16_t *) NLA_DATA(na);
+	if (na->nla_type != CTRL_ATTR_FAMILY_ID)
+		rd_fatal("unexpected family id");
 
-	return id;
+	return *(uint16_t *) NLA_DATA(na);
 }
 
 void print_procacct(int fd, struct taskstats *t)
@@ -375,7 +372,7 @@ int process_netlink_events(struct fd_handler *el)
 
 		if (msg.n.nlmsg_type == NLMSG_ERROR || !NLMSG_OK((&msg.n), ret)) {
 			struct nlmsgerr *err = NLMSG_DATA(&msg);
-			rd_fatal("fatal reply error, errno=%d", err->error);
+			rd_fatal("reply error: %s (errno=%d)", strerror(-err->error), err->error);
 		}
 
 		ret = GENLMSG_PAYLOAD(&msg.n);
-- 
2.33.8



^ permalink raw reply	[flat|nested] 12+ messages in thread

* [make-initrd] [PATCH v1 06/11] feature/procacct: Use nonblocking per-call
  2023-06-15 17:59 [make-initrd] [PATCH v1 00/11] Add accounting feature Alexey Gladkov
                   ` (4 preceding siblings ...)
  2023-06-15 17:59 ` [make-initrd] [PATCH v1 05/11] feature/procacct: Use msgtemplate instead of custom struct Alexey Gladkov
@ 2023-06-15 17:59 ` Alexey Gladkov
  2023-06-15 17:59 ` [make-initrd] [PATCH v1 07/11] feature/procacct: Add bpf helper Alexey Gladkov
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Alexey Gladkov @ 2023-06-15 17:59 UTC (permalink / raw)
  To: make-initrd

Signed-off-by: Alexey Gladkov <gladkov.alexey@gmail.com>
---
 features/debug-procacct/src/procacct.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/features/debug-procacct/src/procacct.c b/features/debug-procacct/src/procacct.c
index 0ff9030f..151a6f2c 100644
--- a/features/debug-procacct/src/procacct.c
+++ b/features/debug-procacct/src/procacct.c
@@ -144,7 +144,7 @@ void setup_netlink_fd(struct fd_handler *el)
 {
 	struct sockaddr_nl local;
 
-	el->fd = socket(AF_NETLINK, SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC, NETLINK_GENERIC);
+	el->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
 	if (el->fd < 0)
 		rd_fatal("error creating Netlink socket: %m");
 
@@ -361,7 +361,7 @@ int process_netlink_events(struct fd_handler *el)
 		struct nlattr *na;
 
 		errno = 0;
-		ret = recv(el->fd, &msg, sizeof(msg), 0);
+		ret = recv(el->fd, &msg, sizeof(msg), MSG_DONTWAIT);
 		if (ret < 0) {
 			if (errno == EAGAIN || errno == EWOULDBLOCK)
 				return 0;
-- 
2.33.8



^ permalink raw reply	[flat|nested] 12+ messages in thread

* [make-initrd] [PATCH v1 07/11] feature/procacct: Add bpf helper
  2023-06-15 17:59 [make-initrd] [PATCH v1 00/11] Add accounting feature Alexey Gladkov
                   ` (5 preceding siblings ...)
  2023-06-15 17:59 ` [make-initrd] [PATCH v1 06/11] feature/procacct: Use nonblocking per-call Alexey Gladkov
@ 2023-06-15 17:59 ` Alexey Gladkov
  2023-06-15 17:59 ` [make-initrd] [PATCH v1 08/11] feature/procacct: Add accounting report Alexey Gladkov
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Alexey Gladkov @ 2023-06-15 17:59 UTC (permalink / raw)
  To: make-initrd

This bpf helper translates to userspace information about the arguments
to the execve system call. This is necessary because taskstats has no
other information about the process other than its comm. In the case of
shell scripts and some other cases, comm is not very informative.

Of course, in this approach, a race situation is possible between an
event from a bpf program and a netlink event. In this case, a memory
leak will occur because no one will remove the entry from the tree.

Signed-off-by: Alexey Gladkov <gladkov.alexey@gmail.com>
---
 features/debug-procacct/src/Makefile.mk    |  17 ++-
 features/debug-procacct/src/procacct-bpf.c |  57 ++++++++
 features/debug-procacct/src/procacct.c     | 153 +++++++++++++++++++--
 features/debug-procacct/src/procacct.h     |  13 ++
 4 files changed, 224 insertions(+), 16 deletions(-)
 create mode 100644 features/debug-procacct/src/procacct-bpf.c
 create mode 100644 features/debug-procacct/src/procacct.h

diff --git a/features/debug-procacct/src/Makefile.mk b/features/debug-procacct/src/Makefile.mk
index ea02bf91..505d8288 100644
--- a/features/debug-procacct/src/Makefile.mk
+++ b/features/debug-procacct/src/Makefile.mk
@@ -1,6 +1,19 @@
 procacct_DEST = $(dest_data_bindir)/procacct
 procacct_SRCS = $(FEATURESDIR)/debug-procacct/src/procacct.c
-procacct_CFLAGS = -D_GNU_SOURCE -Idatasrc/libinitramfs
-procacct_LIBS = -L$(dest_data_libdir) -linitramfs
+procacct_CFLAGS = -D_GNU_SOURCE -Idatasrc/libinitramfs -DPROCACCT_BPF_FILE=\"/bin/procacct-bpf.o\"
+procacct_LIBS = -L$(dest_data_libdir) -linitramfs -lbpf
 
 PROGS += procacct
+
+procacct_bpf_DEST = $(dest_data_bindir)/procacct-bpf.o
+procacct_bpf_SRCS = $(FEATURESDIR)/debug-procacct/src/procacct-bpf.c
+
+CLANG ?= clang-15
+LLVM_STRIP = llvm-strip
+
+$(dest_data_bindir)/procacct-bpf.o: $(procacct_bpf_SRCS)
+	$(Q)mkdir -p -- $(dir $@)
+	$(call quiet_cmd,BPF,$@,$(CLANG)) -target bpf -g -O2 -Wall -Wextra -o $@ -c $<
+	$(call quiet_cmd,STRIP,$@,$(LLVM_STRIP)) -g $@
+
+build-progs: $(dest_data_bindir)/procacct-bpf.o
diff --git a/features/debug-procacct/src/procacct-bpf.c b/features/debug-procacct/src/procacct-bpf.c
new file mode 100644
index 00000000..2dbd25d8
--- /dev/null
+++ b/features/debug-procacct/src/procacct-bpf.c
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <linux/bpf.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_core_read.h>
+#include <bpf/bpf_tracing.h>
+
+#include "procacct.h"
+
+char _license[] SEC("license") = "GPL";
+
+struct mm_struct {
+	unsigned long arg_start, arg_end, env_start, env_end;
+} __attribute__((preserve_access_index));
+
+struct task_struct {
+	pid_t pid;
+	struct mm_struct *mm;
+} __attribute__((preserve_access_index));
+
+struct {
+	__uint(type, BPF_MAP_TYPE_RINGBUF);
+	__uint(max_entries, 256 * sizeof(struct task_cmdline));
+} ringbuf SEC(".maps");
+
+SEC("raw_tracepoint/sched_process_exec")
+int procacct_process_exec(struct bpf_raw_tracepoint_args *ctx __attribute__((unused)))
+{
+	struct task_cmdline *buf;
+
+	struct task_struct *task = (void *) bpf_get_current_task_btf();
+	char *arg_start = (char *) BPF_CORE_READ(task, mm, arg_start);
+	char *arg_end   = (char *) BPF_CORE_READ(task, mm, arg_end);
+	size_t len = arg_end - arg_start;
+
+	buf = bpf_ringbuf_reserve(&ringbuf, sizeof(*buf), 0);
+	if (!buf)
+		return 0;
+
+	if (len >= sizeof(buf->cmdline))
+		len = sizeof(buf->cmdline);
+
+	if (bpf_probe_read_user(buf->cmdline, len, arg_start)) {
+		bpf_ringbuf_discard(buf, 0);
+		return 0;
+	}
+
+	buf->pid = BPF_CORE_READ(task, pid);
+	buf->cmdline_len = len;
+
+	bpf_ringbuf_submit(buf, 0);
+	return 0;
+}
diff --git a/features/debug-procacct/src/procacct.c b/features/debug-procacct/src/procacct.c
index 151a6f2c..51c81734 100644
--- a/features/debug-procacct/src/procacct.c
+++ b/features/debug-procacct/src/procacct.c
@@ -27,6 +27,9 @@
 #include <linux/taskstats.h>
 #include <linux/kdev_t.h>
 
+#include <bpf/bpf.h>
+#include <bpf/libbpf.h>
+
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/socket.h>
@@ -46,6 +49,8 @@
 #include "rd/logging.h"
 #include "rd/memory.h"
 
+#include "procacct.h"
+
 /* Maximum size of response requested or message sent */
 #define MAX_MSG_SIZE 2048
 
@@ -73,20 +78,27 @@ struct msgtemplate {
 	char buf[MAX_MSG_SIZE];
 };
 
-static void *proc_root = NULL;
-
-struct proc_cmdline {
+struct cmdline {
 	pid_t pid;
 	char *cmdline;
 };
 
+static void *tree_root = NULL;
+
 struct ctx_netlink {
 	uint16_t cpuid;
 	uint16_t cpumask_len;
 	char cpumask[100 + 6 * MAX_CPUS];
 };
 
+struct ctx_bpf {
+	struct ring_buffer *ringbuf;
+	struct bpf_object *file;
+	struct bpf_link *link;
+};
+
 enum {
+	FD_BPF,
 	FD_NETLINK,
 	FD_MAX,
 };
@@ -107,11 +119,15 @@ struct fd_handler {
 static struct fd_handler fd_handler_list[FD_MAX];
 
 static void usage(void)                                                       __attribute__((noreturn));
-static int proc_compare(const void *a, const void *b)                         __attribute__((nonnull(1, 2)));
+static int tree_compare(const void *a, const void *b)                         __attribute__((nonnull(1, 2)));
 static int process_netlink_events(struct fd_handler *el);
 static int prepare_netlink(struct fd_handler *el);
 static int finish_netlink(struct fd_handler *el);
 static void setup_netlink_fd(struct fd_handler *el);
+static int process_ringbuf_event(void *ctx, void *data, size_t data_sz);
+static int process_bpf_events(struct fd_handler *el);
+static int finish_bpf(struct fd_handler *el);
+static void setup_bpf_fd(struct fd_handler *el);
 static ssize_t send_cmd(int fd, uint16_t nlmsg_type, uint8_t genl_cmd,
                         uint16_t nla_type, void *nla_data, uint16_t nla_len);
 static uint16_t get_family_id(int fd);
@@ -119,10 +135,10 @@ static void print_procacct(int fd, struct taskstats *t)                       __
 static void handle_aggr(struct nlattr *na, int fd)                            __attribute__((nonnull(1)));
 static int setup_epoll_fd(struct fd_handler list[FD_MAX]);
 
-int proc_compare(const void *a, const void *b)
+int tree_compare(const void *a, const void *b)
 {
-	pid_t pid_a = ((struct proc_cmdline *)a)->pid;
-	pid_t pid_b = ((struct proc_cmdline *)b)->pid;
+	pid_t pid_a = ((struct cmdline *)a)->pid;
+	pid_t pid_b = ((struct cmdline *)b)->pid;
 
 	if (pid_a < pid_b)
 		return -1;
@@ -243,8 +259,10 @@ uint16_t get_family_id(int fd)
 
 void print_procacct(int fd, struct taskstats *t)
 {
-	struct proc_cmdline key = { .pid = (pid_t) t->ac_pid };
-	struct proc_cmdline *proc = tfind(&key, proc_root, proc_compare);
+	struct cmdline *proc, key = { .pid = (pid_t) t->ac_pid };
+	void **val = tfind(&key, &tree_root, tree_compare);
+
+	proc = (val ? *val : NULL);
 
 	dprintf(fd,
 	        "%c\t%u\t%u\t%u\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t%llu\t[%s]\t%s\n",
@@ -263,8 +281,14 @@ void print_procacct(int fd, struct taskstats *t)
 	        (t->read_bytes),                     // bytes of read I/O
 	        (t->write_bytes),                    // bytes of write I/O
 	        (t->ac_comm),                        // comm
-	        (proc ? proc->cmdline : "")          // cmdline
+	        (proc ? proc->cmdline : "-")         // cmdline
 	       );
+
+	if (proc) {
+		tdelete(proc, &tree_root, tree_compare);
+		free(proc->cmdline);
+		free(proc);
+	}
 }
 
 void handle_aggr(struct nlattr *na, int fd)
@@ -317,14 +341,14 @@ int prepare_netlink(struct fd_handler *el)
 
 	ctx->cpuid = get_family_id(el->fd);
 	if (!ctx->cpuid) {
-		rd_err("error getting family id, errno=%d", errno);
+		rd_err("error getting family id (errno=%d): %m", errno);
 		free(ctx);
 		return -1;
 	}
 
 	ret = send_cmd(el->fd, ctx->cpuid, TASKSTATS_CMD_GET,
 	               TASKSTATS_CMD_ATTR_REGISTER_CPUMASK,
-		       &ctx->cpumask, ctx->cpumask_len);
+	               &ctx->cpumask, ctx->cpumask_len);
 	if (ret < 0) {
 		rd_err("error sending register cpumask");
 		free(ctx);
@@ -343,7 +367,7 @@ int finish_netlink(struct fd_handler *el)
 
 	ret = send_cmd(el->fd, ctx->cpuid, TASKSTATS_CMD_GET,
 	               TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK,
-		       &ctx->cpumask, ctx->cpumask_len);
+	               &ctx->cpumask, ctx->cpumask_len);
 	if (ret < 0) {
 		rd_err("error sending deregister cpumask");
 		return -1;
@@ -367,7 +391,7 @@ int process_netlink_events(struct fd_handler *el)
 				return 0;
 			if (errno == EINTR)
 				continue;
-			rd_fatal("nonfatal reply error: %m");
+			rd_fatal("fatal reply error: %m");
 		}
 
 		if (msg.n.nlmsg_type == NLMSG_ERROR || !NLMSG_OK((&msg.n), ret)) {
@@ -401,6 +425,105 @@ int process_netlink_events(struct fd_handler *el)
 	return 0;
 }
 
+int process_ringbuf_event(void *ctx __attribute__((unused)),
+                          void *data,
+                          size_t data_sz  __attribute__((unused)))
+{
+	struct cmdline *new, **val;
+	struct task_cmdline *task = data;
+
+	new = rd_malloc_or_die(sizeof(*new));
+
+	new->pid = task->pid;
+	new->cmdline = rd_calloc_or_die(1, task->cmdline_len * sizeof(char));
+
+	for (size_t i = 0; i < task->cmdline_len; i++) {
+		switch (task->cmdline[i]) {
+			case '\n':
+			case '\0':
+				new->cmdline[i] = ' ';
+				break;
+			default:
+				new->cmdline[i] = task->cmdline[i];
+				break;
+		}
+	}
+
+	val = tsearch(new, &tree_root, tree_compare);
+
+	if (!val) {
+		rd_err("unable to add info about pid=%u", task->pid);
+
+	} else if (*val != new) {
+		struct cmdline *cur = *val;
+
+		free(cur->cmdline);
+		cur->cmdline = new->cmdline;
+		free(new);
+	}
+
+	return 0;
+}
+
+int process_bpf_events(struct fd_handler *el)
+{
+	struct ctx_bpf *ctx = el->data;
+again:
+	errno = 0;
+	if (ring_buffer__poll(ctx->ringbuf, -1) < 0) {
+		if (errno == EINTR)
+			goto again;
+		rd_err("error polling perf buffer: %m");
+	}
+	return 0;
+}
+
+void setup_bpf_fd(struct fd_handler *el)
+{
+	struct ctx_bpf *ctx;
+	struct bpf_program *prog;
+
+	ctx = rd_calloc_or_die(1, sizeof(*ctx));
+
+	ctx->file = bpf_object__open(PROCACCT_BPF_FILE);
+	if (libbpf_get_error(ctx->file))
+		rd_fatal("opening BPF object file failed");
+
+	if (bpf_object__load(ctx->file))
+		rd_fatal("loading BPF object file failed");
+
+	prog = bpf_object__find_program_by_name(ctx->file, "procacct_process_exec");
+	if (!prog)
+		rd_fatal("finding a procacct_task_alloc in the file object failed");
+
+	int id = bpf_object__find_map_fd_by_name(ctx->file, "ringbuf");
+	if (id < 0)
+		rd_fatal("finding a ringbuf in the file object failed");
+
+	ctx->ringbuf = ring_buffer__new(id, process_ringbuf_event, NULL, NULL);
+
+	ctx->link = bpf_program__attach(prog);
+	if (libbpf_get_error(ctx->link))
+		rd_fatal("bpf attach failed");
+
+	el->fd = ring_buffer__epoll_fd(ctx->ringbuf);
+
+	el->data = ctx;
+	el->fd_handler = process_bpf_events;
+	el->fd_finish = finish_bpf;
+}
+
+int finish_bpf(struct fd_handler *el)
+{
+	struct ctx_bpf *ctx = el->data;
+
+	ring_buffer__free(ctx->ringbuf);
+	bpf_link__destroy(ctx->link);
+	bpf_object__close(ctx->file);
+
+	return 0;
+}
+
 int setup_epoll_fd(struct fd_handler list[FD_MAX])
 {
 	int epollfd;
@@ -454,6 +577,8 @@ int main(int argc, char *argv[])
 	current_pid = getpid();
 
 	setup_netlink_fd(&fd_handler_list[FD_NETLINK]);
+	setup_bpf_fd(&fd_handler_list[FD_BPF]);
+
 	fd_epoll = setup_epoll_fd(fd_handler_list);
 
 	for (int i = 0; i < FD_MAX; i++) {
diff --git a/features/debug-procacct/src/procacct.h b/features/debug-procacct/src/procacct.h
new file mode 100644
index 00000000..cd783bc2
--- /dev/null
+++ b/features/debug-procacct/src/procacct.h
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#ifndef __PROCACCT_H__
+#define __PROCACCT_H__
+
+#define MAX_ARGS_LEN 4096
+
+struct task_cmdline {
+	pid_t pid;
+	size_t cmdline_len;
+	char cmdline[MAX_ARGS_LEN];
+};
+
+#endif /* __PROCACCT_H__ */
-- 
2.33.8



^ permalink raw reply	[flat|nested] 12+ messages in thread

* [make-initrd] [PATCH v1 08/11] feature/procacct: Add accounting report
  2023-06-15 17:59 [make-initrd] [PATCH v1 00/11] Add accounting feature Alexey Gladkov
                   ` (6 preceding siblings ...)
  2023-06-15 17:59 ` [make-initrd] [PATCH v1 07/11] feature/procacct: Add bpf helper Alexey Gladkov
@ 2023-06-15 17:59 ` Alexey Gladkov
  2023-06-15 17:59 ` [make-initrd] [PATCH v1 09/11] feature/procacct: Wait until procacct is initialized Alexey Gladkov
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Alexey Gladkov @ 2023-06-15 17:59 UTC (permalink / raw)
  To: make-initrd

Process the raw report and display it in a more user-friendly way just
before system init execution. It is possible to control which values to
include in the report sing the boot cmdline parameter rdacct="..." .

Signed-off-by: Alexey Gladkov <gladkov.alexey@gmail.com>
---
 data/etc/rc.d/rc.sysexec                      |  12 ++
 data/etc/rc.d/rc.sysinit                      |  23 +++-
 features/debug-procacct/config.mk             |   2 +-
 .../debug-procacct/data/bin/procacct-report   | 117 ++++++++++++++++++
 .../data/etc/initrd/cmdline.d/procacct        |   1 +
 features/debug-procacct/rules.mk              |   2 +-
 6 files changed, 149 insertions(+), 8 deletions(-)
 create mode 100755 features/debug-procacct/data/bin/procacct-report
 create mode 100644 features/debug-procacct/data/etc/initrd/cmdline.d/procacct

diff --git a/data/etc/rc.d/rc.sysexec b/data/etc/rc.d/rc.sysexec
index eaa859a4..af2549fe 100755
--- a/data/etc/rc.d/rc.sysexec
+++ b/data/etc/rc.d/rc.sysexec
@@ -3,6 +3,18 @@
 . /.initrd/initenv
 . /etc/init.d/functions
 
+if [ -s /tmp/procacct.stats ]; then
+	printf '### Accounting Results ###\n'
+	/bin/procacct-report /tmp/procacct.stats
+	printf '### Accounting Done ###\n'
+fi
+
+if [ -s /tmp/procacct.err ]; then
+	printf '### Accounting Error ###\n'
+	cat /tmp/procacct.err
+	printf '### Accounting FAILES ###\n'
+fi
+
 ! mountpoint -q /proc ||
 	umount -fl /proc
 
diff --git a/data/etc/rc.d/rc.sysinit b/data/etc/rc.d/rc.sysinit
index 8e0ee7fd..de63bfa5 100755
--- a/data/etc/rc.d/rc.sysinit
+++ b/data/etc/rc.d/rc.sysinit
@@ -11,17 +11,23 @@ dmesg -n "${LOGLEVEL:-1}"
 
 mount -n -t proc -o nodev,noexec,nosuid proc /proc
 
+have_acct=
 quiet=n
-__set_quiet()
+__handler()
 {
-	[ "$1" = 'quiet' ] ||
-		return 0
-	quiet=y
-	[ -z "$2" ] || ! shell_var_is_no "$2" || quiet=n
+	case "${1,,}" in
+		quiet)
+			quiet=y
+			[ -z "$2" ] || ! shell_var_is_no "$2" || quiet=n
+			;;
+		rdacct)
+			have_acct=1
+			;;
+	esac
 }
 
 read -r CMDLINE < /proc/cmdline
-cmdline_foreach "$CMDLINE" __set_quiet
+cmdline_foreach "$CMDLINE" __handler
 
 echo "QUIET=$quiet" >>/etc/sysconfig/init
 
@@ -34,5 +40,10 @@ if shell_var_is_no "$quiet"; then
 	}
 fi
 
+if [ -n "$have_acct" ]; then
+	mount -n -t sysfs sysfs /sys
+	/bin/procacct -o /tmp/procacct.stats 2>/tmp/procacct.err &
+fi
+
 # Alt-Uparrow
 spawn-shell ${CONSOLE_KEYSTROKE:-alt keycode 103} &
diff --git a/features/debug-procacct/config.mk b/features/debug-procacct/config.mk
index 8b137891..06dcf603 100644
--- a/features/debug-procacct/config.mk
+++ b/features/debug-procacct/config.mk
@@ -1 +1 @@
-
+PROCACCT_DATA = $(FEATURESDIR)/debug-procacct/data
diff --git a/features/debug-procacct/data/bin/procacct-report b/features/debug-procacct/data/bin/procacct-report
new file mode 100755
index 00000000..049c50e8
--- /dev/null
+++ b/features/debug-procacct/data/bin/procacct-report
@@ -0,0 +1,117 @@
+#!/bin/bash -efu
+# SPDX-License-Identifier: GPL-2.0
+
+. shell-error
+. shell-quote
+
+readonly def_type=top
+readonly def_kind=cputime:rssusage:etime
+readonly def_limit=10
+
+readonly procacct_stats_file="$1"
+shift
+
+if [ "$#" -eq 0 ]; then
+	[ ! -f /.initrd/initenv ] || . /.initrd/initenv
+
+	if [ -n "${RDACCT-}" ] && [ "${RDACCT-}" != 1 ]; then
+		quote_shell_variable vars "${RDACCT//,/ }"
+		eval -- "$vars"
+	fi
+else
+	kind="${1//:/ }"
+fi
+
+type="${type:-$def_type}"
+kind="${kind:-$def_kind}"
+limit="${limit:-$def_limit}"
+
+set -- ${kind//:/ }
+
+for (( i=$#; i > 0; i-- )) do
+	case "$1" in
+		iobytes) set -- "$@" iorbytes iowbytes ;;
+		bytes)   set -- "$@" rbytes wbytes     ;;
+		*)       set -- "$@" "$1"              ;;
+	esac
+	shift
+done
+
+i=0; FIELD=(); DESC=(); UNIT=();
+
+F_TYPE=$(( $i + 1 ))     ; FIELD[$i]=""         ; DESC[$i]=""                ; UNIT[$i]=""      ; i=$(( $i + 1 ))
+F_PID=$(( $i + 1 ))      ; FIELD[$i]=""         ; DESC[$i]=""                ; UNIT[$i]=""      ; i=$(( $i + 1 ))
+F_TGID=$(( $i + 1 ))     ; FIELD[$i]=""         ; DESC[$i]=""                ; UNIT[$i]=""      ; i=$(( $i + 1 ))
+F_PPID=$(( $i + 1 ))     ; FIELD[$i]=""         ; DESC[$i]=""                ; UNIT[$i]=""      ; i=$(( $i + 1 ))
+F_BTIME=$(( $i + 1 ))    ; FIELD[$i]=""         ; DESC[$i]=""                ; UNIT[$i]=""      ; i=$(( $i + 1 ))
+F_ETIME=$(( $i + 1 ))    ; FIELD[$i]="etime"    ; DESC[$i]="Elapsed time"    ; UNIT[$i]="usec"  ; i=$(( $i + 1 ))
+F_CPUTIME=$(( $i + 1 ))  ; FIELD[$i]="cputime"  ; DESC[$i]="CPU time"        ; UNIT[$i]="usec"  ; i=$(( $i + 1 ))
+F_VMUSAGE=$(( $i + 1 ))  ; FIELD[$i]="vmusage"  ; DESC[$i]="VM usage"        ; UNIT[$i]="kb"    ; i=$(( $i + 1 ))
+F_RSSUSAGE=$(( $i + 1 )) ; FIELD[$i]="rssusage" ; DESC[$i]="RSS usage"       ; UNIT[$i]="kb"    ; i=$(( $i + 1 ))
+F_RBYTES=$(( $i + 1 ))   ; FIELD[$i]="rbytes"   ; DESC[$i]="Read bytes"      ; UNIT[$i]="bytes" ; i=$(( $i + 1 ))
+F_WBYTES=$(( $i + 1 ))   ; FIELD[$i]="wbytes"   ; DESC[$i]="Write bytes"     ; UNIT[$i]="bytes" ; i=$(( $i + 1 ))
+F_IORBYTES=$(( $i + 1 )) ; FIELD[$i]="iorbytes" ; DESC[$i]="Read I/O bytes"  ; UNIT[$i]="bytes" ; i=$(( $i + 1 ))
+F_IOWBYTES=$(( $i + 1 )) ; FIELD[$i]="iowbytes" ; DESC[$i]="Write I/O bytes" ; UNIT[$i]="bytes" ; i=$(( $i + 1 ))
+F_COMM=$(( $i + 1 ))     ; FIELD[$i]=""         ; DESC[$i]=""                ; UNIT[$i]=""      ; i=$(( $i + 1 ))
+F_CMDLINE=$(( $i + 1 ))  ; FIELD[$i]=""         ; DESC[$i]=""                ; UNIT[$i]=""      ; i=$(( $i + 1 ))
+
+cut_output()
+{
+	case "$limit" in
+		(-[1-9]*) tail -n "${limit#-}" ;;
+		( [1-9]*) head -n "$limit" ;;
+		(   ''|0) cat ;;
+	esac
+}
+
+output_top()
+{
+	printf '%s:\n' "Top $limit of ${DESC[$index]}"
+
+	cut -f "${F_TYPE},${F_PID},${F_TGID},${F_BTIME},${field},${F_COMM}-" \
+		"$1" |
+	while IFS='	' read -r ptype pid tgid btime data comm cmdline; do
+		date="$(date -u +'%Y-%m-%d %H:%M:%S' -d "@$btime" 2>/dev/null)" ||
+			date="@$btime secs"
+
+		case "$ptype" in
+			P) name="Process" ;;
+			T) name="Thread $pid" ;;
+			*) name="Unknown thing id=$pid" ;;
+		esac
+
+		[ "$cmdline" != - ] ||
+			cmdline="$comm"
+
+		printf '  * %s (pid=%s):\n' "$name" "$tgid"
+		printf '    - %-15s: %s\n' "Start time"      "$date"
+		printf '    - %-15s: %s\n' "${DESC[$index]}" "$data ${UNIT[$index]}"
+		printf '    - %-15s: %s\n' "Command"         "$cmdline"
+	done
+	printf '\n'
+}
+
+data_file="/tmp/$PROG.stats"
+
+for by_kind; do
+	by_kind="${by_kind,,}"
+
+	for index in "${!FIELD[@]}" 0; do
+		[ "${FIELD[$index]}" != "$by_kind" ] ||
+			break
+	done
+
+	[ $index -gt 0 ] ||
+		continue
+
+	field=$(( $index + 1 ))
+
+	sort -nrk "$field,$field" "$procacct_stats_file" |
+		cut_output > "$data_file"
+
+	case "$type" in
+		top) output_top "$data_file" ;;
+	esac
+
+	echo rm -f -- "$data_file"
+done
diff --git a/features/debug-procacct/data/etc/initrd/cmdline.d/procacct b/features/debug-procacct/data/etc/initrd/cmdline.d/procacct
new file mode 100644
index 00000000..99474627
--- /dev/null
+++ b/features/debug-procacct/data/etc/initrd/cmdline.d/procacct
@@ -0,0 +1 @@
+register_parameter string RDACCT
diff --git a/features/debug-procacct/rules.mk b/features/debug-procacct/rules.mk
index 8b137891..5aabfbd2 100644
--- a/features/debug-procacct/rules.mk
+++ b/features/debug-procacct/rules.mk
@@ -1 +1 @@
-
+PUT_FEATURE_DIRS += $(PROCACCT_DATA)
-- 
2.33.8



^ permalink raw reply	[flat|nested] 12+ messages in thread

* [make-initrd] [PATCH v1 09/11] feature/procacct: Wait until procacct is initialized
  2023-06-15 17:59 [make-initrd] [PATCH v1 00/11] Add accounting feature Alexey Gladkov
                   ` (7 preceding siblings ...)
  2023-06-15 17:59 ` [make-initrd] [PATCH v1 08/11] feature/procacct: Add accounting report Alexey Gladkov
@ 2023-06-15 17:59 ` Alexey Gladkov
  2023-06-15 17:59 ` [make-initrd] [PATCH v1 10/11] feature/procacct: Make procacct optional Alexey Gladkov
  2023-06-15 17:59 ` [make-initrd] [PATCH v1 11/11] feature/procacct: Add to testing Alexey Gladkov
  10 siblings, 0 replies; 12+ messages in thread
From: Alexey Gladkov @ 2023-06-15 17:59 UTC (permalink / raw)
  To: make-initrd

Signed-off-by: Alexey Gladkov <gladkov.alexey@gmail.com>
---
 data/etc/rc.d/rc.sysinit               |  3 +++
 features/debug-procacct/src/procacct.c | 12 ++++++------
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/data/etc/rc.d/rc.sysinit b/data/etc/rc.d/rc.sysinit
index de63bfa5..bdc3c907 100755
--- a/data/etc/rc.d/rc.sysinit
+++ b/data/etc/rc.d/rc.sysinit
@@ -43,6 +43,9 @@ fi
 if [ -n "$have_acct" ]; then
 	mount -n -t sysfs sysfs /sys
 	/bin/procacct -o /tmp/procacct.stats 2>/tmp/procacct.err &
+	while [ ! -f /tmp/procacct.stats ]; do
+		sleep 0.1
+	done
 fi
 
 # Alt-Uparrow
diff --git a/features/debug-procacct/src/procacct.c b/features/debug-procacct/src/procacct.c
index 51c81734..bbee9ef7 100644
--- a/features/debug-procacct/src/procacct.c
+++ b/features/debug-procacct/src/procacct.c
@@ -568,12 +568,6 @@ int main(int argc, char *argv[])
 		}
 	}
 
-	if (write_file) {
-		fd_out = open(logfile, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, 0644);
-		if (fd_out < 0)
-			rd_fatal("cannot open output file: %s: %m", logfile);
-	}
-
 	current_pid = getpid();
 
 	setup_netlink_fd(&fd_handler_list[FD_NETLINK]);
@@ -588,6 +582,12 @@ int main(int argc, char *argv[])
 			rd_fatal("unable to prepare file descriptor");
 	}
 
+	if (write_file) {
+		fd_out = open(logfile, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, 0644);
+		if (fd_out < 0)
+			rd_fatal("cannot open output file: %s: %m", logfile);
+	}
+
 	while (1) {
 		struct epoll_event ev[EV_MAX];
 		int fdcount;
-- 
2.33.8



^ permalink raw reply	[flat|nested] 12+ messages in thread

* [make-initrd] [PATCH v1 10/11] feature/procacct: Make procacct optional
  2023-06-15 17:59 [make-initrd] [PATCH v1 00/11] Add accounting feature Alexey Gladkov
                   ` (8 preceding siblings ...)
  2023-06-15 17:59 ` [make-initrd] [PATCH v1 09/11] feature/procacct: Wait until procacct is initialized Alexey Gladkov
@ 2023-06-15 17:59 ` Alexey Gladkov
  2023-06-15 17:59 ` [make-initrd] [PATCH v1 11/11] feature/procacct: Add to testing Alexey Gladkov
  10 siblings, 0 replies; 12+ messages in thread
From: Alexey Gladkov @ 2023-06-15 17:59 UTC (permalink / raw)
  To: make-initrd

Signed-off-by: Alexey Gladkov <gladkov.alexey@gmail.com>
---
 Makefile.in                             | 10 +++++++
 configure.ac                            | 36 +++++++++++++++++++++++++
 features/debug-procacct/src/Makefile.mk |  7 ++---
 3 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/Makefile.in b/Makefile.in
index 45053fa0..c26a3f44 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -90,8 +90,15 @@ HAVE_LIBINIPARSER        := @HAVE_LIBINIPARSER@
 HAVE_LIBINIPARSER_LIBS   := @HAVE_LIBINIPARSER_LIBS@
 HAVE_LIBINIPARSER_CFLAGS := @HAVE_LIBINIPARSER_CFLAGS@
 
+HAVE_LIBBPF        := @HAVE_LIBBPF@
+HAVE_LIBBPF_LIBS   := @HAVE_LIBBPF_LIBS@
+HAVE_LIBBPF_CFLAGS := @HAVE_LIBBPF_CFLAGS@
+
 USE_FEATURE_BOOTLOADER = @USE_FEATURE_BOOTLOADER@
+USE_FEATURE_PROCACCT = @USE_FEATURE_PROCACCT@
 
+CLANG ?= @CLANG@
+LLVM_STRIP ?= @LLVM_STRIP@
 YACC := @YACC@
 LEX  := @LEX@
 
@@ -108,6 +115,9 @@ SKIP_FEATURES =
 ifeq ($(USE_FEATURE_BOOTLOADER),no)
 SKIP_FEATURES += bootloader
 endif
+ifeq ($(USE_FEATURE_PROCACCT),no)
+SKIP_FEATURES += debug-procacct
+endif
 
 all: build
 
diff --git a/configure.ac b/configure.ac
index 9633a2ba..db2575e4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -314,6 +314,41 @@ if test "x$with_feature_bootloader" != xno; then
 	fi
 fi
 
+AC_ARG_WITH([feature-procacct],
+	[AS_HELP_STRING([--with-feature-procacct],
+			[build procacct feature (default: auto)])],
+	[],
+	[: m4_divert_text([DEFAULTS], [with_feature_procacct=auto])])
+
+USE_FEATURE_PROCACCT=no
+HAVE_LIBBPF=no
+
+if test "x$with_feature_procacct" != xno; then
+	PKG_CHECK_MODULES(HAVE_LIBBPF, libbpf, [HAVE_LIBBPF=yes], [HAVE_LIBBPF=no]);
+	AC_PATH_PROGS([with_clang], [clang])
+	AC_PATH_PROGS([with_llvm_strip], [llvm-strip])
+
+	if test "x$with_feature_procacct" != xauto; then
+		AS_IF([test "x$HAVE_LIBBPF" != xyes],
+			[AC_MSG_ERROR([libbpf was not found: https://github.com/libbpf/libbpf])])
+		AS_IF([! test -x "$with_clang"],
+			[AC_MSG_ERROR([required utility not found: clang])])
+	fi
+
+	if test "x-$HAVE_LIBBPF" = x-yes && test -x "$with_clang"; then
+		USE_FEATURE_PROCACCT=yes
+	fi
+
+	if ! test -x "$with_llvm_strip"; then
+		with_llvm_strip=/bin/true
+	fi
+
+	AC_SUBST([HAVE_LIBBPF])
+	AC_SUBST([CLANG], [$with_clang])
+	AC_SUBST([LLVM_STRIP], [$with_llvm_strip])
+fi
+
+
 AC_SUBST([HAVE_GZIP])
 AC_SUBST([HAVE_BZIP2])
 AC_SUBST([HAVE_LZMA])
@@ -326,6 +361,7 @@ AC_SUBST([HAVE_LIBINIPARSER])
 AC_SUBST([HAVE_LIBINIPARSER_LIBS])
 AC_SUBST([HAVE_LIBINIPARSER_CFLAGS])
 AC_SUBST([USE_FEATURE_BOOTLOADER])
+AC_SUBST([USE_FEATURE_PROCACCT])
 AC_SUBST([MKLOCAL])
 AC_SUBST([YACC])
 AC_SUBST([LEX])
diff --git a/features/debug-procacct/src/Makefile.mk b/features/debug-procacct/src/Makefile.mk
index 505d8288..43589b1a 100644
--- a/features/debug-procacct/src/Makefile.mk
+++ b/features/debug-procacct/src/Makefile.mk
@@ -1,16 +1,13 @@
 procacct_DEST = $(dest_data_bindir)/procacct
 procacct_SRCS = $(FEATURESDIR)/debug-procacct/src/procacct.c
-procacct_CFLAGS = -D_GNU_SOURCE -Idatasrc/libinitramfs -DPROCACCT_BPF_FILE=\"/bin/procacct-bpf.o\"
-procacct_LIBS = -L$(dest_data_libdir) -linitramfs -lbpf
+procacct_CFLAGS = -D_GNU_SOURCE -Idatasrc/libinitramfs $(HAVE_LIBBPF_CFLAGS) -DPROCACCT_BPF_FILE=\"/bin/procacct-bpf.o\"
+procacct_LIBS = -L$(dest_data_libdir) -linitramfs $(HAVE_LIBBPF_LIBS)
 
 PROGS += procacct
 
 procacct_bpf_DEST = $(dest_data_bindir)/procacct-bpf.o
 procacct_bpf_SRCS = $(FEATURESDIR)/debug-procacct/src/procacct-bpf.c
 
-CLANG ?= clang-15
-LLVM_STRIP = llvm-strip
-
 $(dest_data_bindir)/procacct-bpf.o: $(procacct_bpf_SRCS)
 	$(Q)mkdir -p -- $(dir $@)
 	$(call quiet_cmd,BPF,$@,$(CLANG)) -target bpf -g -O2 -Wall -Wextra -o $@ -c $<
-- 
2.33.8



^ permalink raw reply	[flat|nested] 12+ messages in thread

* [make-initrd] [PATCH v1 11/11] feature/procacct: Add to testing
  2023-06-15 17:59 [make-initrd] [PATCH v1 00/11] Add accounting feature Alexey Gladkov
                   ` (9 preceding siblings ...)
  2023-06-15 17:59 ` [make-initrd] [PATCH v1 10/11] feature/procacct: Make procacct optional Alexey Gladkov
@ 2023-06-15 17:59 ` Alexey Gladkov
  10 siblings, 0 replies; 12+ messages in thread
From: Alexey Gladkov @ 2023-06-15 17:59 UTC (permalink / raw)
  To: make-initrd

Signed-off-by: Alexey Gladkov <gladkov.alexey@gmail.com>
---
 testing/packages-altlinux                   | 3 ++-
 testing/test-root-btrfs-subvol.cfg          | 2 +-
 testing/test-root-efi-partition.cfg         | 2 +-
 testing/test-root-efi-reqpartition.cfg      | 2 +-
 testing/test-root-luks+crypttab+noparam.cfg | 2 +-
 testing/test-root-luks+lukskey-noparam.cfg  | 2 +-
 testing/test-root-luks+lukskey-plain.cfg    | 2 +-
 testing/test-root-luks+lukskey-raw.cfg      | 2 +-
 testing/test-root-luks-over-lvm.cfg         | 2 +-
 testing/test-root-luks-over-raid1.cfg       | 2 +-
 testing/test-root-luks.cfg                  | 2 +-
 testing/test-root-lvm+luks.cfg              | 2 +-
 testing/test-root-lvm.cfg                   | 2 +-
 testing/test-root-partition+usr.cfg         | 2 +-
 testing/test-root-partition.cfg             | 2 +-
 testing/test-root-pipeline.cfg              | 2 +-
 testing/test-root-raid1+raid5.cfg           | 2 +-
 testing/test-root-raid1-degraded.cfg        | 2 +-
 testing/test-root-raid1.cfg                 | 2 +-
 testing/test-root-raid5.cfg                 | 2 +-
 testing/test-root-sshfs-network-dhcp.cfg    | 2 +-
 testing/test-root-sshfs-network-static1.cfg | 2 +-
 testing/test-root-zfs-partition.cfg         | 2 +-
 testing/testing-altlinux-local              | 9 +++++++++
 testing/testing-ks-initrd.cfg               | 1 +
 25 files changed, 34 insertions(+), 23 deletions(-)

diff --git a/testing/packages-altlinux b/testing/packages-altlinux
index 68472aa2..d164e5f6 100644
--- a/testing/packages-altlinux
+++ b/testing/packages-altlinux
@@ -1,11 +1,12 @@
 #!/bin/bash
 
-MAKE_INITRD_PACKAGES="make udev libelf libkmod zlib bzlib libzstd liblzma"
+MAKE_INITRD_PACKAGES="make udev libelf libkmod zlib bzlib libzstd liblzma libbpf"
 
 MAKE_INITRD_PACKAGES_DEVEL="$MAKE_INITRD_PACKAGES"
 MAKE_INITRD_PACKAGES_DEVEL+=" gcc make automake autoconf bison flex"
 MAKE_INITRD_PACKAGES_DEVEL+=" libkmod-devel zlib-devel bzlib-devel liblzma-devel"
 MAKE_INITRD_PACKAGES_DEVEL+=" libzstd-devel libelf-devel libtirpc-devel libcrypt-devel"
+MAKE_INITRD_PACKAGES_DEVEL+=" llvm clang libbpf-devel"
 
 KERNEL_PACKAGES="kernel-image$KERNEL_FLAVOR"
 
diff --git a/testing/test-root-btrfs-subvol.cfg b/testing/test-root-btrfs-subvol.cfg
index a33a03f9..23153a76 100644
--- a/testing/test-root-btrfs-subvol.cfg
+++ b/testing/test-root-btrfs-subvol.cfg
@@ -1,6 +1,6 @@
 # param KICKSTART_DISKS=5
 # param BOOT_DISKS=5
-# param BOOT_CMDLINE="$BOOT_CMDLINE rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=fs rootflags=subvol=root"
+# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=fs rootflags=subvol=root"
 
 ignoredisk --drives=LABEL=SYSIMAGE
 clearpart --all --initlabel --disklabel=mbr
diff --git a/testing/test-root-efi-partition.cfg b/testing/test-root-efi-partition.cfg
index acd0f24c..b0f58d20 100644
--- a/testing/test-root-efi-partition.cfg
+++ b/testing/test-root-efi-partition.cfg
@@ -1,7 +1,7 @@
 # param KICKSTART_DISKS=1
 # param BOOT_DISKS=1
 # param BOOT_BIOS="efi"
-# param BOOT_CMDLINE="$BOOT_CMDLINE rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
+# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
 
 ignoredisk --drives=LABEL=SYSIMAGE
 clearpart --all --initlabel --disklabel=gpt
diff --git a/testing/test-root-efi-reqpartition.cfg b/testing/test-root-efi-reqpartition.cfg
index abaa9535..2da8eb1d 100644
--- a/testing/test-root-efi-reqpartition.cfg
+++ b/testing/test-root-efi-reqpartition.cfg
@@ -1,7 +1,7 @@
 # param KICKSTART_DISKS=1
 # param BOOT_DISKS=1
 # param BOOT_BIOS="efi"
-# param BOOT_CMDLINE="$BOOT_CMDLINE rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
+# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
 
 ignoredisk --drives=LABEL=SYSIMAGE
 clearpart --all --initlabel --disklabel=gpt
diff --git a/testing/test-root-luks+crypttab+noparam.cfg b/testing/test-root-luks+crypttab+noparam.cfg
index cc249779..0e917fc4 100644
--- a/testing/test-root-luks+crypttab+noparam.cfg
+++ b/testing/test-root-luks+crypttab+noparam.cfg
@@ -1,6 +1,6 @@
 # param KICKSTART_DISKS=2
 # param BOOT_DISKS=2
-# param BOOT_CMDLINE="$BOOT_CMDLINE rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
+# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
 
 ignoredisk --drives=LABEL=SYSIMAGE
 clearpart --all --initlabel --disklabel=mbr
diff --git a/testing/test-root-luks+lukskey-noparam.cfg b/testing/test-root-luks+lukskey-noparam.cfg
index 45b83569..94e8974c 100644
--- a/testing/test-root-luks+lukskey-noparam.cfg
+++ b/testing/test-root-luks+lukskey-noparam.cfg
@@ -1,6 +1,6 @@
 # param KICKSTART_DISKS=2
 # param BOOT_DISKS=2
-# param BOOT_CMDLINE="$BOOT_CMDLINE rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
+# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
 
 ignoredisk --drives=LABEL=SYSIMAGE
 clearpart --all --initlabel --disklabel=mbr
diff --git a/testing/test-root-luks+lukskey-plain.cfg b/testing/test-root-luks+lukskey-plain.cfg
index f4cc7399..e5f9eea7 100644
--- a/testing/test-root-luks+lukskey-plain.cfg
+++ b/testing/test-root-luks+lukskey-plain.cfg
@@ -1,6 +1,6 @@
 # param KICKSTART_DISKS=3
 # param BOOT_DISKS=3
-# param BOOT_CMDLINE="$BOOT_CMDLINE rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT luks-key=secret:LABEL=ROOTKEY"
+# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT luks-key=secret:LABEL=ROOTKEY"
 
 ignoredisk --drives=LABEL=SYSIMAGE
 clearpart --all --initlabel --disklabel=mbr
diff --git a/testing/test-root-luks+lukskey-raw.cfg b/testing/test-root-luks+lukskey-raw.cfg
index 1bcef2a1..a5778146 100644
--- a/testing/test-root-luks+lukskey-raw.cfg
+++ b/testing/test-root-luks+lukskey-raw.cfg
@@ -1,6 +1,6 @@
 # param KICKSTART_DISKS=3
 # param BOOT_DISKS=3
-# param BOOT_CMDLINE="$BOOT_CMDLINE rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT luks-key=secret:LABEL=ROOTKEY luks-key-format=raw"
+# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT luks-key=secret:LABEL=ROOTKEY luks-key-format=raw"
 
 ignoredisk --drives=LABEL=SYSIMAGE
 clearpart --all --initlabel --disklabel=mbr
diff --git a/testing/test-root-luks-over-lvm.cfg b/testing/test-root-luks-over-lvm.cfg
index 284da993..f29efc13 100644
--- a/testing/test-root-luks-over-lvm.cfg
+++ b/testing/test-root-luks-over-lvm.cfg
@@ -1,6 +1,6 @@
 # param KICKSTART_DISKS=4
 # param BOOT_DISKS=4
-# param BOOT_CMDLINE="$BOOT_CMDLINE rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
+# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
 # param BOOT_PROG=expect-password
 
 ignoredisk --drives=LABEL=SYSIMAGE
diff --git a/testing/test-root-luks-over-raid1.cfg b/testing/test-root-luks-over-raid1.cfg
index 401ea113..70993e75 100644
--- a/testing/test-root-luks-over-raid1.cfg
+++ b/testing/test-root-luks-over-raid1.cfg
@@ -1,6 +1,6 @@
 # param KICKSTART_DISKS=3
 # param BOOT_DISKS=3
-# param BOOT_CMDLINE="$BOOT_CMDLINE rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
+# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
 # param BOOT_PROG=expect-password
 
 ignoredisk --drives=LABEL=SYSIMAGE
diff --git a/testing/test-root-luks.cfg b/testing/test-root-luks.cfg
index a560285e..2c2f1c82 100644
--- a/testing/test-root-luks.cfg
+++ b/testing/test-root-luks.cfg
@@ -1,6 +1,6 @@
 # param KICKSTART_DISKS=2
 # param BOOT_DISKS=2
-# param BOOT_CMDLINE="$BOOT_CMDLINE rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
+# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
 # param BOOT_PROG=expect-password
 
 ignoredisk --drives=LABEL=SYSIMAGE
diff --git a/testing/test-root-lvm+luks.cfg b/testing/test-root-lvm+luks.cfg
index 093b82e5..b0bff3ca 100644
--- a/testing/test-root-lvm+luks.cfg
+++ b/testing/test-root-lvm+luks.cfg
@@ -1,6 +1,6 @@
 # param KICKSTART_DISKS=5
 # param BOOT_DISKS=5
-# param BOOT_CMDLINE="$BOOT_CMDLINE rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
+# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
 
 ignoredisk --drives=LABEL=SYSIMAGE
 clearpart --all --initlabel --disklabel=mbr
diff --git a/testing/test-root-lvm.cfg b/testing/test-root-lvm.cfg
index b32cc318..f28b477b 100644
--- a/testing/test-root-lvm.cfg
+++ b/testing/test-root-lvm.cfg
@@ -1,6 +1,6 @@
 # param KICKSTART_DISKS=4
 # param BOOT_DISKS=4
-# param BOOT_CMDLINE="$BOOT_CMDLINE rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
+# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
 
 ignoredisk --drives=LABEL=SYSIMAGE
 clearpart --all --initlabel --disklabel=mbr
diff --git a/testing/test-root-partition+usr.cfg b/testing/test-root-partition+usr.cfg
index 8bc27b96..6cc15eb6 100644
--- a/testing/test-root-partition+usr.cfg
+++ b/testing/test-root-partition+usr.cfg
@@ -1,6 +1,6 @@
 # param KICKSTART_DISKS=3
 # param BOOT_DISKS=3
-# param BOOT_CMDLINE="$BOOT_CMDLINE rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
+# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
 
 ignoredisk --drives=LABEL=SYSIMAGE
 clearpart --all --initlabel --disklabel=mbr
diff --git a/testing/test-root-partition.cfg b/testing/test-root-partition.cfg
index f8b439ca..83c70c42 100644
--- a/testing/test-root-partition.cfg
+++ b/testing/test-root-partition.cfg
@@ -1,6 +1,6 @@
 # param KICKSTART_DISKS=2
 # param BOOT_DISKS=2
-# param BOOT_CMDLINE="$BOOT_CMDLINE rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
+# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
 
 ignoredisk --drives=LABEL=SYSIMAGE
 clearpart --all --initlabel --disklabel=mbr
diff --git a/testing/test-root-pipeline.cfg b/testing/test-root-pipeline.cfg
index 2daed048..9fe5cfaf 100644
--- a/testing/test-root-pipeline.cfg
+++ b/testing/test-root-pipeline.cfg
@@ -1,6 +1,6 @@
 # param KICKSTART_DISKS=2
 # param BOOT_DISKS=2
-# param BOOT_CMDLINE="$BOOT_CMDLINE rdlog=console rd-debug-udev=1 quiet panic=0"
+# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rd-debug-udev=1 quiet panic=0"
 # param BOOT_CMDLINE="$BOOT_CMDLINE root=pipeline pipeline=waitdev,mountfs,rootfs waitdev=LABEL=ROOT mountfs=dev"
 
 ignoredisk --drives=LABEL=SYSIMAGE
diff --git a/testing/test-root-raid1+raid5.cfg b/testing/test-root-raid1+raid5.cfg
index 66741260..eab79421 100644
--- a/testing/test-root-raid1+raid5.cfg
+++ b/testing/test-root-raid1+raid5.cfg
@@ -1,6 +1,6 @@
 # param KICKSTART_DISKS=8
 # param BOOT_DISKS=8
-# param BOOT_CMDLINE="$BOOT_CMDLINE rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
+# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
 
 ignoredisk --drives=LABEL=SYSIMAGE
 clearpart --all --initlabel --disklabel=mbr
diff --git a/testing/test-root-raid1-degraded.cfg b/testing/test-root-raid1-degraded.cfg
index a139552c..ddc126c4 100644
--- a/testing/test-root-raid1-degraded.cfg
+++ b/testing/test-root-raid1-degraded.cfg
@@ -1,6 +1,6 @@
 # param KICKSTART_DISKS=3
 # param BOOT_DISKS=2
-# param BOOT_CMDLINE="$BOOT_CMDLINE rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
+# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
 
 ignoredisk --drives=LABEL=SYSIMAGE
 clearpart --all --initlabel --disklabel=mbr
diff --git a/testing/test-root-raid1.cfg b/testing/test-root-raid1.cfg
index ad0c972f..189acb56 100644
--- a/testing/test-root-raid1.cfg
+++ b/testing/test-root-raid1.cfg
@@ -1,6 +1,6 @@
 # param KICKSTART_DISKS=3
 # param BOOT_DISKS=3
-# param BOOT_CMDLINE="$BOOT_CMDLINE rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
+# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
 
 ignoredisk --drives=LABEL=SYSIMAGE
 clearpart --all --initlabel --disklabel=mbr
diff --git a/testing/test-root-raid5.cfg b/testing/test-root-raid5.cfg
index 51e0b238..efce7354 100644
--- a/testing/test-root-raid5.cfg
+++ b/testing/test-root-raid5.cfg
@@ -1,6 +1,6 @@
 # param KICKSTART_DISKS=6
 # param BOOT_DISKS=6
-# param BOOT_CMDLINE="$BOOT_CMDLINE rdlog=console rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
+# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rdlog=console rd-debug-udev=1 quiet panic=0 root=LABEL=ROOT"
 
 ignoredisk --drives=LABEL=SYSIMAGE
 clearpart --all --initlabel --disklabel=mbr
diff --git a/testing/test-root-sshfs-network-dhcp.cfg b/testing/test-root-sshfs-network-dhcp.cfg
index 6114ad44..67dfa803 100644
--- a/testing/test-root-sshfs-network-dhcp.cfg
+++ b/testing/test-root-sshfs-network-dhcp.cfg
@@ -2,6 +2,6 @@
 # param BOOT_DISKS=0
 # param SYSIMAGE_SIZE="mini"
 # param BOOTLOADER_TYPE="none"
-# param BOOT_CMDLINE="$BOOT_CMDLINE rdlog=console rd-debug-udev=1 quiet panic=0"
+# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rd-debug-udev=1 quiet panic=0"
 # param BOOT_CMDLINE="$BOOT_CMDLINE root=/dev/sshfs sshfsroot=sftp@10.0.2.2:/data/incoming sshfsopts=port=2222"
 # param BOOT_CMDLINE="$BOOT_CMDLINE ip=dhcp"
diff --git a/testing/test-root-sshfs-network-static1.cfg b/testing/test-root-sshfs-network-static1.cfg
index 2a285cec..8402e935 100644
--- a/testing/test-root-sshfs-network-static1.cfg
+++ b/testing/test-root-sshfs-network-static1.cfg
@@ -2,6 +2,6 @@
 # param BOOT_DISKS=0
 # param SYSIMAGE_SIZE="mini"
 # param BOOTLOADER_TYPE="none"
-# param BOOT_CMDLINE="$BOOT_CMDLINE rdlog=console rd-debug-udev=1 quiet panic=0"
+# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rd-debug-udev=1 quiet panic=0"
 # param BOOT_CMDLINE="$BOOT_CMDLINE root=/dev/sshfs sshfsroot=sftp@10.0.2.2:/data/incoming sshfsopts=port=2222"
 # param BOOT_CMDLINE="$BOOT_CMDLINE ip=10.0.2.15::10.0.2.1:255.255.255.0:localhost:eth0:none"
diff --git a/testing/test-root-zfs-partition.cfg b/testing/test-root-zfs-partition.cfg
index 729bf89b..320c9e7b 100644
--- a/testing/test-root-zfs-partition.cfg
+++ b/testing/test-root-zfs-partition.cfg
@@ -2,7 +2,7 @@
 # param BOOT_DISKS=3
 # param SYSIMAGE_EXTRA_PACKAGES+=" $ZFS_PACKAGES"
 # param KICKSTART_PACKAGES+=" $ZFS_PACKAGES"
-# param BOOT_CMDLINE="$BOOT_CMDLINE rdlog=console rd-debug-udev=1 quiet panic=0 root=ZFS=rpool/ROOT zfs.force=1"
+# param BOOT_CMDLINE="$BOOT_CMDLINE rdacct=1 rdlog=console rd-debug-udev=1 quiet panic=0 root=ZFS=rpool/ROOT zfs.force=1"
 
 ignoredisk --drives=LABEL=SYSIMAGE
 clearpart --all --initlabel --disklabel=mbr
diff --git a/testing/testing-altlinux-local b/testing/testing-altlinux-local
index c1f111b8..38e8f366 100755
--- a/testing/testing-altlinux-local
+++ b/testing/testing-altlinux-local
@@ -45,6 +45,15 @@ for step in "$@"; do
 			cd "$builddir"
 			rc=0
 
+			ALTWRAP_LLVM_VERSION="\$(
+				rpmquery -a --qf='%{name}\n' llvm\*-libs |
+				sed -e 's/^llvm//' -e 's/-libs//' |
+				sort -g |
+				tail -1
+			)"
+			[ -z "\$ALTWRAP_LLVM_VERSION" ] ||
+				export ALTWRAP_LLVM_VERSION
+
 			./autogen.sh
 			./configure \
 				--enable-local-build \
diff --git a/testing/testing-ks-initrd.cfg b/testing/testing-ks-initrd.cfg
index 558c060e..890cd5f5 100644
--- a/testing/testing-ks-initrd.cfg
+++ b/testing/testing-ks-initrd.cfg
@@ -21,6 +21,7 @@
 	tee /etc/initrd.mk <<-EOF
 	AUTODETECT = all
 	MODULES_PRELOAD += virtio-blk virtio-scsi
+	FEATURES += debug-procacct
 	`[ ! -f /etc/initrd.mk.addon ] || cat /etc/initrd.mk.addon`
 	EOF
 
-- 
2.33.8



^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2023-06-15 17:59 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-15 17:59 [make-initrd] [PATCH v1 00/11] Add accounting feature Alexey Gladkov
2023-06-15 17:59 ` [make-initrd] [PATCH v1 01/11] feature/procacct: New feature to debug initramfs Alexey Gladkov
2023-06-15 17:59 ` [make-initrd] [PATCH v1 02/11] feature/procacct: Use epoll Alexey Gladkov
2023-06-15 17:59 ` [make-initrd] [PATCH v1 03/11] feature/procacct: Use default rcvbufsz Alexey Gladkov
2023-06-15 17:59 ` [make-initrd] [PATCH v1 04/11] feature/procacct: Track more values Alexey Gladkov
2023-06-15 17:59 ` [make-initrd] [PATCH v1 05/11] feature/procacct: Use msgtemplate instead of custom struct Alexey Gladkov
2023-06-15 17:59 ` [make-initrd] [PATCH v1 06/11] feature/procacct: Use nonblocking per-call Alexey Gladkov
2023-06-15 17:59 ` [make-initrd] [PATCH v1 07/11] feature/procacct: Add bpf helper Alexey Gladkov
2023-06-15 17:59 ` [make-initrd] [PATCH v1 08/11] feature/procacct: Add accounting report Alexey Gladkov
2023-06-15 17:59 ` [make-initrd] [PATCH v1 09/11] feature/procacct: Wait until procacct is initialized Alexey Gladkov
2023-06-15 17:59 ` [make-initrd] [PATCH v1 10/11] feature/procacct: Make procacct optional Alexey Gladkov
2023-06-15 17:59 ` [make-initrd] [PATCH v1 11/11] feature/procacct: Add to testing Alexey Gladkov

Make-initrd development discussion

This inbox may be cloned and mirrored by anyone:

	git clone --mirror http://lore.altlinux.org/make-initrd/0 make-initrd/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 make-initrd make-initrd/ http://lore.altlinux.org/make-initrd \
		make-initrd@lists.altlinux.org make-initrd@lists.altlinux.ru make-initrd@lists.altlinux.com
	public-inbox-index make-initrd

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://lore.altlinux.org/org.altlinux.lists.make-initrd


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git