Include meminfo-writer
It is common for dom0 and VM, so keep in one place for both of them.
This commit is contained in:
parent
5afa710f21
commit
f0b1271a5e
2
Makefile
2
Makefile
@ -16,10 +16,12 @@ rpms:
|
||||
rpmbuild --define "_rpmdir rpm/" --define "_builddir ." -bb rpm_spec/qubes-utils.spec
|
||||
all:
|
||||
$(MAKE) -C qrexec-lib all
|
||||
$(MAKE) -C qmemman all
|
||||
|
||||
install:
|
||||
$(MAKE) -C udev install
|
||||
$(MAKE) -C qrexec-lib install
|
||||
$(MAKE) -C qmemman install
|
||||
|
||||
clean:
|
||||
$(MAKE) -C qrexec-lib clean
|
||||
|
11
qmemman/Makefile
Normal file
11
qmemman/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
CC=gcc
|
||||
CFLAGS=-Wall -g -O3
|
||||
all: meminfo-writer
|
||||
meminfo-writer: meminfo-writer.o
|
||||
$(CC) -g -o meminfo-writer meminfo-writer.o -lxenstore
|
||||
install:
|
||||
install -D meminfo-writer $(DESTDIR)/usr/sbin/meminfo-writer
|
||||
install -d $(DESTDIR)/usr/lib/systemd/system/
|
||||
install qubes-meminfo-writer*service $(DESTDIR)/usr/lib/systemd/system/
|
||||
clean:
|
||||
rm -f meminfo-writer xenstore-watch *.o
|
176
qmemman/meminfo-writer.c
Normal file
176
qmemman/meminfo-writer.c
Normal file
@ -0,0 +1,176 @@
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <xs.h>
|
||||
#include <syslog.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
unsigned long prev_used_mem;
|
||||
int used_mem_change_threshold;
|
||||
int delay;
|
||||
int usr1_received;
|
||||
|
||||
char *parse(char *buf)
|
||||
{
|
||||
char *ptr = buf;
|
||||
char name[256];
|
||||
static char outbuf[4096];
|
||||
int val;
|
||||
int len;
|
||||
int MemTotal = 0, MemFree = 0, Buffers = 0, Cached = 0, SwapTotal =
|
||||
0, SwapFree = 0;
|
||||
unsigned long long key;
|
||||
long used_mem, used_mem_diff;
|
||||
int nitems = 0;
|
||||
|
||||
while (nitems != 6) {
|
||||
sscanf(ptr, "%s %d kB\n%n", name, &val, &len);
|
||||
key = *(unsigned long long *) ptr;
|
||||
if (key == *(unsigned long long *) "MemTotal:") {
|
||||
MemTotal = val;
|
||||
nitems++;
|
||||
} else if (key == *(unsigned long long *) "MemFree:") {
|
||||
MemFree = val;
|
||||
nitems++;
|
||||
} else if (key == *(unsigned long long *) "Buffers:") {
|
||||
Buffers = val;
|
||||
nitems++;
|
||||
} else if (key == *(unsigned long long *) "Cached: ") {
|
||||
Cached = val;
|
||||
nitems++;
|
||||
} else if (key == *(unsigned long long *) "SwapTotal:") {
|
||||
SwapTotal = val;
|
||||
nitems++;
|
||||
} else if (key == *(unsigned long long *) "SwapFree:") {
|
||||
SwapFree = val;
|
||||
nitems++;
|
||||
}
|
||||
|
||||
ptr += len;
|
||||
}
|
||||
|
||||
used_mem =
|
||||
MemTotal - Buffers - Cached - MemFree + SwapTotal - SwapFree;
|
||||
if (used_mem < 0)
|
||||
return NULL;
|
||||
|
||||
used_mem_diff = used_mem - prev_used_mem;
|
||||
if (used_mem_diff < 0)
|
||||
used_mem_diff = -used_mem_diff;
|
||||
if (used_mem_diff > used_mem_change_threshold
|
||||
|| (used_mem > prev_used_mem && used_mem * 13 / 10 > MemTotal
|
||||
&& used_mem_diff > used_mem_change_threshold/2)) {
|
||||
prev_used_mem = used_mem;
|
||||
sprintf(outbuf,
|
||||
"MemTotal: %d kB\nMemFree: %d kB\nBuffers: %d kB\nCached: %d kB\n"
|
||||
"SwapTotal: %d kB\nSwapFree: %d kB\n", MemTotal,
|
||||
MemFree, Buffers, Cached, SwapTotal, SwapFree);
|
||||
return outbuf;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void usage()
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: meminfo_writer threshold_in_kb delay_in_us [pidfile]\n");
|
||||
fprintf(stderr, " When pidfile set, meminfo-writer will:\n");
|
||||
fprintf(stderr, " - fork into background\n");
|
||||
fprintf(stderr, " - wait for SIGURS1 (in background) before starting main work\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void send_to_qmemman(struct xs_handle *xs, char *data)
|
||||
{
|
||||
if (!xs_write(xs, XBT_NULL, "memory/meminfo", data, strlen(data))) {
|
||||
syslog(LOG_DAEMON | LOG_ERR, "error writing xenstore ?");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void usr1_handler(int sig) {
|
||||
usr1_received = 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char buf[4096];
|
||||
int n;
|
||||
char *meminfo_data;
|
||||
int fd;
|
||||
struct xs_handle *xs;
|
||||
|
||||
if (argc != 3 && argc != 4)
|
||||
usage();
|
||||
used_mem_change_threshold = atoi(argv[1]);
|
||||
delay = atoi(argv[2]);
|
||||
if (!used_mem_change_threshold || !delay)
|
||||
usage();
|
||||
|
||||
if (argc == 4) {
|
||||
pid_t pid;
|
||||
sigset_t mask, oldmask;
|
||||
|
||||
switch (pid = fork()) {
|
||||
case -1:
|
||||
perror("fork");
|
||||
exit(1);
|
||||
case 0:
|
||||
sigemptyset (&mask);
|
||||
sigaddset (&mask, SIGUSR1);
|
||||
/* Wait for a signal to arrive. */
|
||||
sigprocmask (SIG_BLOCK, &mask, &oldmask);
|
||||
usr1_received = 0;
|
||||
signal(SIGUSR1, usr1_handler);
|
||||
while (!usr1_received)
|
||||
sigsuspend (&oldmask);
|
||||
sigprocmask (SIG_UNBLOCK, &mask, NULL);
|
||||
break;
|
||||
default:
|
||||
fd = open(argv[3], O_CREAT | O_TRUNC | O_WRONLY, 0666);
|
||||
if (fd < 0) {
|
||||
perror("open pidfile");
|
||||
exit(1);
|
||||
}
|
||||
n = sprintf(buf, "%d\n", pid);
|
||||
if (write(fd, buf, n) != n) {
|
||||
perror("write pid");
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
fd = open("/proc/meminfo", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
perror("open meminfo");
|
||||
exit(1);
|
||||
}
|
||||
xs = xs_domain_open();
|
||||
if (!xs) {
|
||||
perror("xs_domain_open");
|
||||
exit(1);
|
||||
}
|
||||
if (argc == 3) {
|
||||
/* if not waiting for signal, fork after first info written to xenstore */
|
||||
n = pread(fd, buf, sizeof(buf), 0);
|
||||
buf[n] = 0;
|
||||
meminfo_data = parse(buf);
|
||||
if (meminfo_data)
|
||||
send_to_qmemman(xs, meminfo_data);
|
||||
if (fork() > 0)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
n = pread(fd, buf, sizeof(buf), 0);
|
||||
buf[n] = 0;
|
||||
meminfo_data = parse(buf);
|
||||
if (meminfo_data)
|
||||
send_to_qmemman(xs, meminfo_data);
|
||||
usleep(delay);
|
||||
}
|
||||
}
|
13
qmemman/qubes-meminfo-writer-dom0.service
Normal file
13
qmemman/qubes-meminfo-writer-dom0.service
Normal file
@ -0,0 +1,13 @@
|
||||
[Unit]
|
||||
Description=Qubes memory information reporter
|
||||
After=qubes-core.service qubes-qmemman.service
|
||||
ConditionPathExists=/var/run/qubes/qmemman.sock
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/sbin/meminfo-writer 30000 100000
|
||||
StandardOutput=syslog
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
12
qmemman/qubes-meminfo-writer.service
Normal file
12
qmemman/qubes-meminfo-writer.service
Normal file
@ -0,0 +1,12 @@
|
||||
[Unit]
|
||||
Description=Qubes memory information reporter
|
||||
ConditionPathExists=/var/run/qubes-service/meminfo-writer
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
ExecStart=/usr/sbin/meminfo-writer 30000 100000 /var/run/meminfo-writer.pid
|
||||
PIDFile=/var/run/meminfo-writer.pid
|
||||
StandardOutput=syslog
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@ -34,6 +34,21 @@ make all
|
||||
%install
|
||||
make install DESTDIR=%{buildroot}
|
||||
|
||||
%post
|
||||
if [ -r /etc/qubes-release ]; then
|
||||
# dom0
|
||||
/bin/systemctl enable qubes-meminfo-writer-dom0.service > /dev/null 2>&1
|
||||
else
|
||||
# VM
|
||||
/bin/systemctl enable qubes-meminfo-writer.service > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
%postun
|
||||
if [ $1 -eq 0 ]; then
|
||||
/bin/systemctl disable qubes-meminfo-writer.service > /dev/null 2>&1
|
||||
/bin/systemctl disable qubes-meminfo-writer.service > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
@ -41,6 +56,9 @@ rm -rf $RPM_BUILD_ROOT
|
||||
%defattr(-,root,root,-)
|
||||
/etc/udev/rules.d/99-qubes-*.rules
|
||||
/usr/libexec/qubes/udev-*
|
||||
%{_sbindir}/meminfo-writer
|
||||
%{_unitdir}/qubes-meminfo-writer.service
|
||||
%{_unitdir}/qubes-meminfo-writer-dom0.service
|
||||
|
||||
|
||||
%files devel
|
||||
|
Loading…
Reference in New Issue
Block a user