// SPDX-License-Identifier: GPL-2.0
/*
 * memcg_event_listener.c - Simple listener of memcg memory.events
 *
 * Copyright (c) 2023, SaluteDevices. All Rights Reserved.
 *
 * Author: Dmitry Rokosov <ddrokosov@salutedevices.com>
 */

#include <err.h>
#include <errno.h>
#include <limits.h>
#include <poll.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/inotify.h>
#include <unistd.h>

#define MEMCG_EVENTS "memory.events"

/* Size of buffer to use when reading inotify events */
#define INOTIFY_BUFFER_SIZE 8192

#define INOTIFY_EVENT_NEXT(event, length) ({         \
	(length) -= sizeof(*(event)) + (event)->len; \
	(event)++;                                   \
})

#define INOTIFY_EVENT_OK(event, length) ((length) >= (ssize_t)sizeof(*(event)))

#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))

struct memcg_counters {
	long low;
	long high;
	long max;
	long oom;
	long oom_kill;
	long oom_group_kill;
};

struct memcg_events {
	struct memcg_counters counters;
	char path[PATH_MAX];
	int inotify_fd;
	int inotify_wd;
};

static void print_memcg_counters(const struct memcg_counters *counters)
{
	printf("MEMCG events:\n");
	printf("\tlow: %ld\n", counters->low);
	printf("\thigh: %ld\n", counters->high);
	printf("\tmax: %ld\n", counters->max);
	printf("\toom: %ld\n", counters->oom);
	printf("\toom_kill: %ld\n", counters->oom_kill);
	printf("\toom_group_kill: %ld\n", counters->oom_group_kill);
}

static int get_memcg_counter(char *line, const char *name, long *counter)
{
	size_t len = strlen(name);
	char *endptr;
	long tmp;

	if (memcmp(line, name, len)) {
		warnx("Counter line %s has wrong name, %s is expected",
		      line, name);
		return -EINVAL;
	}

	/* skip the whitespace delimiter */
	len += 1;

	errno = 0;
	tmp = strtol(&line[len], &endptr, 10);
	if (((tmp == LONG_MAX || tmp == LONG_MIN) && errno == ERANGE) ||
	    (errno && !tmp)) {
		warnx("Failed to parse: %s", &line[len]);
		return -ERANGE;
	}

	if (endptr == &line[len]) {
		warnx("Not digits were found in line %s", &line[len]);
		return -EINVAL;
	}

	if (!(*endptr == '\0' || (*endptr == '\n' && *++endptr == '\0'))) {
		warnx("Further characters after number: %s", endptr);
		return -EINVAL;
	}

	*counter = tmp;

	return 0;
}

static int read_memcg_events(struct memcg_events *events, bool show_diff)
{
	FILE *fp = fopen(events->path, "re");
	size_t i;
	int ret = 0;
	bool any_new_events = false;
	char *line = NULL;
	size_t len = 0;
	struct memcg_counters new_counters;
	struct memcg_counters *counters = &events->counters;
	struct {
		const char *name;
		long *new;
		long *old;
	} map[] = {
		{
			.name = "low",
			.new = &new_counters.low,
			.old = &counters->low,
		},
		{
			.name = "high",
			.new = &new_counters.high,
			.old = &counters->high,
		},
		{
			.name = "max",
			.new = &new_counters.max,
			.old = &counters->max,
		},
		{
			.name = "oom",
			.new = &new_counters.oom,
			.old = &counters->oom,
		},
		{
			.name = "oom_kill",
			.new = &new_counters.oom_kill,
			.old = &counters->oom_kill,
		},
		{
			.name = "oom_group_kill",
			.new = &new_counters.oom_group_kill,
			.old = &counters->oom_group_kill,
		},
	};

	if (!fp) {
		warn("Failed to open memcg events file %s", events->path);
		return -EBADF;
	}

	/* Read new values for memcg counters */
	for (i = 0; i < ARRAY_SIZE(map); ++i) {
		ssize_t nread;

		errno = 0;
		nread = getline(&line, &len, fp);
		if (nread == -1) {
			if (errno) {
				warn("Failed to read line for counter %s",
				     map[i].name);
				ret = -EIO;
				goto exit;
			}

			break;
		}

		ret = get_memcg_counter(line, map[i].name, map[i].new);
		if (ret) {
			warnx("Failed to get counter value from line %s", line);
			goto exit;
		}
	}

	for (i = 0; i < ARRAY_SIZE(map); ++i) {
		long diff;

		if (*map[i].new > *map[i].old) {
			diff = *map[i].new - *map[i].old;

			if (show_diff)
				printf("*** %ld MEMCG %s event%s, "
				       "change counter %ld => %ld\n",
				       diff, map[i].name,
				       (diff == 1) ? "" : "s",
				       *map[i].old, *map[i].new);

			*map[i].old += diff;
			any_new_events = true;
		}
	}

	if (show_diff && !any_new_events)
		printf("*** No new untracked memcg events available\n");

exit:
	free(line);
	fclose(fp);

	return ret;
}

static void process_memcg_events(struct memcg_events *events,
				 struct inotify_event *event)
{
	int ret;

	if (events->inotify_wd != event->wd) {
		warnx("Unknown inotify event %d, should be %d", event->wd,
		      events->inotify_wd);
		return;
	}

	printf("Received event in %s:\n", events->path);

	if (!(event->mask & IN_MODIFY)) {
		warnx("No IN_MODIFY event, skip it");
		return;
	}

	ret = read_memcg_events(events, /* show_diff = */true);
	if (ret)
		warnx("Can't read memcg events");
}

static void monitor_events(struct memcg_events *events)
{
	struct pollfd fds[1];
	int ret;

	printf("Started monitoring memory events from '%s'...\n", events->path);

	fds[0].fd = events->inotify_fd;
	fds[0].events = POLLIN;

	for (;;) {
		ret = poll(fds, ARRAY_SIZE(fds), -1);
		if (ret < 0 && errno != EAGAIN)
			err(EXIT_FAILURE, "Can't poll memcg events (%d)", ret);

		if (fds[0].revents & POLLERR)
			err(EXIT_FAILURE, "Got POLLERR during monitor events");

		if (fds[0].revents & POLLIN) {
			struct inotify_event *event;
			char buffer[INOTIFY_BUFFER_SIZE];
			ssize_t length;

			length = read(fds[0].fd, buffer, INOTIFY_BUFFER_SIZE);
			if (length <= 0)
				continue;

			event = (struct inotify_event *)buffer;
			while (INOTIFY_EVENT_OK(event, length)) {
				process_memcg_events(events, event);
				event = INOTIFY_EVENT_NEXT(event, length);
			}
		}
	}
}

static int initialize_memcg_events(struct memcg_events *events,
				   const char *cgroup)
{
	int ret;

	memset(events, 0, sizeof(struct memcg_events));

	ret = snprintf(events->path, PATH_MAX,
		       "/sys/fs/cgroup/%s/memory.events", cgroup);
	if (ret >= PATH_MAX) {
		warnx("Path to cgroup memory.events is too long");
		return -EMSGSIZE;
	} else if (ret < 0) {
		warn("Can't generate cgroup event full name");
		return ret;
	}

	ret = read_memcg_events(events, /* show_diff = */false);
	if (ret) {
		warnx("Failed to read initial memcg events state (%d)", ret);
		return ret;
	}

	events->inotify_fd = inotify_init();
	if (events->inotify_fd < 0) {
		warn("Failed to setup new inotify device");
		return -EMFILE;
	}

	events->inotify_wd = inotify_add_watch(events->inotify_fd,
					       events->path, IN_MODIFY);
	if (events->inotify_wd < 0) {
		warn("Couldn't add monitor in dir %s", events->path);
		return -EIO;
	}

	printf("Initialized MEMCG events with counters:\n");
	print_memcg_counters(&events->counters);

	return 0;
}

static void cleanup_memcg_events(struct memcg_events *events)
{
	inotify_rm_watch(events->inotify_fd, events->inotify_wd);
	close(events->inotify_fd);
}

int main(int argc, const char **argv)
{
	struct memcg_events events;
	ssize_t ret;

	if (argc != 2)
		errx(EXIT_FAILURE, "Usage: %s <cgroup>", argv[0]);

	ret = initialize_memcg_events(&events, argv[1]);
	if (ret)
		errx(EXIT_FAILURE, "Can't initialize memcg events (%zd)", ret);

	monitor_events(&events);

	cleanup_memcg_events(&events);

	printf("Exiting memcg event listener...\n");

	return EXIT_SUCCESS;
}
